mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
layout: Store table parts in DOM layout data (#36447)
When laying out tables, store the boxes of non-anonymous table parts in their respective DOM objects. This is going to be important for incremental layout, but also for mapping from the DOM to the box tree (and eventually the fragment tree). For now, anonymous table parts are still lost to time and space, but in a followup change we hope to store them somewhere. Testing: This has no visible change to web rendering, so is covered by existing WPT. Co-authored-by: Oriol Brufau <obrufau@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
a4a308e434
commit
56e7c21fe7
8 changed files with 229 additions and 143 deletions
|
@ -8,7 +8,7 @@ use std::ops::Deref;
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
|
||||||
pub(crate) struct ArcRefCell<T> {
|
pub struct ArcRefCell<T> {
|
||||||
value: Arc<AtomicRefCell<T>>,
|
value: Arc<AtomicRefCell<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ use crate::flow::BlockLevelBox;
|
||||||
use crate::flow::inline::InlineItem;
|
use crate::flow::inline::InlineItem;
|
||||||
use crate::geom::PhysicalSize;
|
use crate::geom::PhysicalSize;
|
||||||
use crate::replaced::{CanvasInfo, CanvasSource};
|
use crate::replaced::{CanvasInfo, CanvasSource};
|
||||||
|
use crate::table::TableLevelBox;
|
||||||
use crate::taffy::TaffyItemBox;
|
use crate::taffy::TaffyItemBox;
|
||||||
|
|
||||||
/// The data that is stored in each DOM node that is used by layout.
|
/// The data that is stored in each DOM node that is used by layout.
|
||||||
|
@ -43,6 +44,7 @@ pub(super) enum LayoutBox {
|
||||||
BlockLevel(ArcRefCell<BlockLevelBox>),
|
BlockLevel(ArcRefCell<BlockLevelBox>),
|
||||||
InlineLevel(ArcRefCell<InlineItem>),
|
InlineLevel(ArcRefCell<InlineItem>),
|
||||||
FlexLevel(ArcRefCell<FlexLevelBox>),
|
FlexLevel(ArcRefCell<FlexLevelBox>),
|
||||||
|
TableLevelBox(TableLevelBox),
|
||||||
TaffyItemBox(ArcRefCell<TaffyItemBox>),
|
TaffyItemBox(ArcRefCell<TaffyItemBox>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ impl LayoutBox {
|
||||||
LayoutBox::TaffyItemBox(taffy_item_box) => {
|
LayoutBox::TaffyItemBox(taffy_item_box) => {
|
||||||
taffy_item_box.borrow_mut().invalidate_cached_fragment()
|
taffy_item_box.borrow_mut().invalidate_cached_fragment()
|
||||||
},
|
},
|
||||||
|
LayoutBox::TableLevelBox(table_box) => table_box.invalidate_cached_fragment(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,7 @@ impl BoxTree {
|
||||||
},
|
},
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
|
LayoutBox::TableLevelBox(..) => return None,
|
||||||
LayoutBox::TaffyItemBox(taffy_level_box) => match &taffy_level_box
|
LayoutBox::TaffyItemBox(taffy_level_box) => match &taffy_level_box
|
||||||
.borrow()
|
.borrow()
|
||||||
.taffy_level_box
|
.taffy_level_box
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub mod table;
|
||||||
pub mod traversal;
|
pub mod traversal;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
pub use cell::ArcRefCell;
|
||||||
pub use flow::BoxTree;
|
pub use flow::BoxTree;
|
||||||
pub use fragment_tree::FragmentTree;
|
pub use fragment_tree::FragmentTree;
|
||||||
use style::logical_geometry::WritingMode;
|
use style::logical_geometry::WritingMode;
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::borrow::Cow;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
|
||||||
|
use atomic_refcell::AtomicRef;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
|
use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -15,13 +16,13 @@ use style::selector_parser::PseudoElement;
|
||||||
use style::str::char_is_whitespace;
|
use style::str::char_is_whitespace;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Table, TableCaption, TableSlot, TableSlotCell, TableSlotCoordinates, TableSlotOffset,
|
Table, TableCaption, TableLevelBox, TableSlot, TableSlotCell, TableSlotCoordinates,
|
||||||
TableTrack, TableTrackGroup, TableTrackGroupType,
|
TableSlotOffset, TableTrack, TableTrackGroup, TableTrackGroupType,
|
||||||
};
|
};
|
||||||
use crate::PropagatedBoxTreeData;
|
use crate::PropagatedBoxTreeData;
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom::{BoxSlot, NodeExt};
|
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
|
||||||
use crate::flow::{BlockContainerBuilder, BlockFormattingContext};
|
use crate::flow::{BlockContainerBuilder, BlockFormattingContext};
|
||||||
use crate::formatting_contexts::{
|
use crate::formatting_contexts::{
|
||||||
|
@ -33,9 +34,9 @@ use crate::layout_box_base::LayoutBoxBase;
|
||||||
use crate::style_ext::{DisplayGeneratingBox, DisplayLayoutInternal};
|
use crate::style_ext::{DisplayGeneratingBox, DisplayLayoutInternal};
|
||||||
|
|
||||||
/// A reference to a slot and its coordinates in the table
|
/// A reference to a slot and its coordinates in the table
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct ResolvedSlotAndLocation<'a> {
|
pub(super) struct ResolvedSlotAndLocation<'a> {
|
||||||
pub cell: &'a TableSlotCell,
|
pub cell: AtomicRef<'a, TableSlotCell>,
|
||||||
pub coords: TableSlotCoordinates,
|
pub coords: TableSlotCoordinates,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +162,10 @@ impl Table {
|
||||||
) -> Vec<ResolvedSlotAndLocation<'_>> {
|
) -> Vec<ResolvedSlotAndLocation<'_>> {
|
||||||
let slot = self.get_slot(coords);
|
let slot = self.get_slot(coords);
|
||||||
match slot {
|
match slot {
|
||||||
Some(TableSlot::Cell(cell)) => vec![ResolvedSlotAndLocation { cell, coords }],
|
Some(TableSlot::Cell(cell)) => vec![ResolvedSlotAndLocation {
|
||||||
|
cell: cell.borrow(),
|
||||||
|
coords,
|
||||||
|
}],
|
||||||
Some(TableSlot::Spanned(offsets)) => offsets
|
Some(TableSlot::Spanned(offsets)) => offsets
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|offset| self.resolve_slot_at(coords - *offset))
|
.flat_map(|offset| self.resolve_slot_at(coords - *offset))
|
||||||
|
@ -241,6 +245,7 @@ impl TableBuilder {
|
||||||
// generally less than or equal to three row groups, but if we notice a lot
|
// generally less than or equal to three row groups, but if we notice a lot
|
||||||
// of web content with more, we can consider a binary search here.
|
// of web content with more, we can consider a binary search here.
|
||||||
for row_group in self.table.row_groups.iter() {
|
for row_group in self.table.row_groups.iter() {
|
||||||
|
let row_group = row_group.borrow();
|
||||||
if row_group.track_range.start > n {
|
if row_group.track_range.start > n {
|
||||||
return row_group.track_range.start - 1;
|
return row_group.track_range.start - 1;
|
||||||
}
|
}
|
||||||
|
@ -286,6 +291,7 @@ impl TableBuilder {
|
||||||
let mut thead_index = None;
|
let mut thead_index = None;
|
||||||
let mut tfoot_index = None;
|
let mut tfoot_index = None;
|
||||||
for (row_group_index, row_group) in self.table.row_groups.iter().enumerate() {
|
for (row_group_index, row_group) in self.table.row_groups.iter().enumerate() {
|
||||||
|
let row_group = row_group.borrow();
|
||||||
if thead_index.is_none() && row_group.group_type == TableTrackGroupType::HeaderGroup {
|
if thead_index.is_none() && row_group.group_type == TableTrackGroupType::HeaderGroup {
|
||||||
thead_index = Some(row_group_index);
|
thead_index = Some(row_group_index);
|
||||||
}
|
}
|
||||||
|
@ -315,25 +321,35 @@ impl TableBuilder {
|
||||||
// Now update all track group ranges.
|
// Now update all track group ranges.
|
||||||
let mut current_row_group_index = None;
|
let mut current_row_group_index = None;
|
||||||
for (row_index, row) in self.table.rows.iter().enumerate() {
|
for (row_index, row) in self.table.rows.iter().enumerate() {
|
||||||
|
let row = row.borrow();
|
||||||
if current_row_group_index == row.group_index {
|
if current_row_group_index == row.group_index {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish any row group that is currently being processed.
|
// Finish any row group that is currently being processed.
|
||||||
if let Some(current_group_index) = current_row_group_index {
|
if let Some(current_group_index) = current_row_group_index {
|
||||||
self.table.row_groups[current_group_index].track_range.end = row_index;
|
self.table.row_groups[current_group_index]
|
||||||
|
.borrow_mut()
|
||||||
|
.track_range
|
||||||
|
.end = row_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start processing this new row group and update its starting index.
|
// Start processing this new row group and update its starting index.
|
||||||
current_row_group_index = row.group_index;
|
current_row_group_index = row.group_index;
|
||||||
if let Some(current_group_index) = current_row_group_index {
|
if let Some(current_group_index) = current_row_group_index {
|
||||||
self.table.row_groups[current_group_index].track_range.start = row_index;
|
self.table.row_groups[current_group_index]
|
||||||
|
.borrow_mut()
|
||||||
|
.track_range
|
||||||
|
.start = row_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the last row group.
|
// Finish the last row group.
|
||||||
if let Some(current_group_index) = current_row_group_index {
|
if let Some(current_group_index) = current_row_group_index {
|
||||||
self.table.row_groups[current_group_index].track_range.end = self.table.rows.len();
|
self.table.row_groups[current_group_index]
|
||||||
|
.borrow_mut()
|
||||||
|
.track_range
|
||||||
|
.end = self.table.rows.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +360,7 @@ impl TableBuilder {
|
||||||
self.table.row_groups.insert(0, removed_row_group);
|
self.table.row_groups.insert(0, removed_row_group);
|
||||||
|
|
||||||
for row in self.table.rows.iter_mut() {
|
for row in self.table.rows.iter_mut() {
|
||||||
|
let mut row = row.borrow_mut();
|
||||||
match row.group_index.as_mut() {
|
match row.group_index.as_mut() {
|
||||||
Some(group_index) if *group_index < index_to_move => *group_index += 1,
|
Some(group_index) if *group_index < index_to_move => *group_index += 1,
|
||||||
Some(group_index) if *group_index == index_to_move => *group_index = 0,
|
Some(group_index) if *group_index == index_to_move => *group_index = 0,
|
||||||
|
@ -352,7 +369,7 @@ impl TableBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let row_range = self.table.row_groups[0].track_range.clone();
|
let row_range = self.table.row_groups[0].borrow().track_range.clone();
|
||||||
if row_range.start > 0 {
|
if row_range.start > 0 {
|
||||||
// Move the slots associated with the moved group.
|
// Move the slots associated with the moved group.
|
||||||
let removed_slots: Vec<Vec<TableSlot>> = self
|
let removed_slots: Vec<Vec<TableSlot>> = self
|
||||||
|
@ -363,7 +380,7 @@ impl TableBuilder {
|
||||||
self.table.slots.splice(0..0, removed_slots);
|
self.table.slots.splice(0..0, removed_slots);
|
||||||
|
|
||||||
// Move the rows associated with the moved group.
|
// Move the rows associated with the moved group.
|
||||||
let removed_rows: Vec<TableTrack> = self
|
let removed_rows: Vec<_> = self
|
||||||
.table
|
.table
|
||||||
.rows
|
.rows
|
||||||
.splice(row_range, std::iter::empty())
|
.splice(row_range, std::iter::empty())
|
||||||
|
@ -385,6 +402,7 @@ impl TableBuilder {
|
||||||
self.table.row_groups.push(removed_row_group);
|
self.table.row_groups.push(removed_row_group);
|
||||||
|
|
||||||
for row in self.table.rows.iter_mut() {
|
for row in self.table.rows.iter_mut() {
|
||||||
|
let mut row = row.borrow_mut();
|
||||||
match row.group_index.as_mut() {
|
match row.group_index.as_mut() {
|
||||||
Some(group_index) if *group_index > index_to_move => *group_index -= 1,
|
Some(group_index) if *group_index > index_to_move => *group_index -= 1,
|
||||||
Some(group_index) if *group_index == index_to_move => {
|
Some(group_index) if *group_index == index_to_move => {
|
||||||
|
@ -396,6 +414,7 @@ impl TableBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
let row_range = self.table.row_groups[last_row_group_index]
|
let row_range = self.table.row_groups[last_row_group_index]
|
||||||
|
.borrow()
|
||||||
.track_range
|
.track_range
|
||||||
.clone();
|
.clone();
|
||||||
if row_range.end < self.table.rows.len() {
|
if row_range.end < self.table.rows.len() {
|
||||||
|
@ -408,7 +427,7 @@ impl TableBuilder {
|
||||||
self.table.slots.extend(removed_slots);
|
self.table.slots.extend(removed_slots);
|
||||||
|
|
||||||
// Move the rows associated with the moved group.
|
// Move the rows associated with the moved group.
|
||||||
let removed_rows: Vec<TableTrack> = self
|
let removed_rows: Vec<_> = self
|
||||||
.table
|
.table
|
||||||
.rows
|
.rows
|
||||||
.splice(row_range, std::iter::empty())
|
.splice(row_range, std::iter::empty())
|
||||||
|
@ -427,6 +446,7 @@ impl TableBuilder {
|
||||||
let last_row_index_in_group = self.last_row_index_in_row_group_at_row_n(row_index);
|
let last_row_index_in_group = self.last_row_index_in_row_group_at_row_n(row_index);
|
||||||
for cell in self.table.slots[row_index].iter_mut() {
|
for cell in self.table.slots[row_index].iter_mut() {
|
||||||
if let TableSlot::Cell(cell) = cell {
|
if let TableSlot::Cell(cell) = cell {
|
||||||
|
let mut cell = cell.borrow_mut();
|
||||||
if cell.rowspan == 1 {
|
if cell.rowspan == 1 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -547,14 +567,17 @@ impl TableBuilder {
|
||||||
/// <https://html.spec.whatwg.org/multipage/#algorithm-for-processing-rows>
|
/// <https://html.spec.whatwg.org/multipage/#algorithm-for-processing-rows>
|
||||||
/// Push a single cell onto the slot map, handling any colspans it may have, and
|
/// Push a single cell onto the slot map, handling any colspans it may have, and
|
||||||
/// setting up the outgoing rowspans.
|
/// setting up the outgoing rowspans.
|
||||||
pub fn add_cell(&mut self, cell: TableSlotCell) {
|
pub fn add_cell(&mut self, cell: ArcRefCell<TableSlotCell>) {
|
||||||
// Make sure the incoming_rowspans table is large enough
|
// Make sure the incoming_rowspans table is large enough
|
||||||
// because we will be writing to it.
|
// because we will be writing to it.
|
||||||
let current_coords = self
|
let current_coords = self
|
||||||
.current_coords()
|
.current_coords()
|
||||||
.expect("Should have rows before calling `add_cell`");
|
.expect("Should have rows before calling `add_cell`");
|
||||||
let colspan = cell.colspan;
|
|
||||||
let rowspan = cell.rowspan;
|
let (colspan, rowspan) = {
|
||||||
|
let cell = cell.borrow();
|
||||||
|
(cell.colspan, cell.rowspan)
|
||||||
|
};
|
||||||
|
|
||||||
if self.incoming_rowspans.len() < current_coords.x + colspan {
|
if self.incoming_rowspans.len() < current_coords.x + colspan {
|
||||||
self.incoming_rowspans
|
self.incoming_rowspans
|
||||||
|
@ -704,21 +727,21 @@ where
|
||||||
row_builder.finish();
|
row_builder.finish();
|
||||||
|
|
||||||
let style = anonymous_info.style.clone();
|
let style = anonymous_info.style.clone();
|
||||||
self.push_table_row(TableTrack {
|
self.push_table_row(ArcRefCell::new(TableTrack {
|
||||||
base_fragment_info: (&anonymous_info).into(),
|
base_fragment_info: (&anonymous_info).into(),
|
||||||
style,
|
style,
|
||||||
group_index: self.current_row_group_index,
|
group_index: self.current_row_group_index,
|
||||||
is_anonymous: true,
|
is_anonymous: true,
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_table_row(&mut self, table_track: TableTrack) {
|
fn push_table_row(&mut self, table_track: ArcRefCell<TableTrack>) {
|
||||||
self.builder.table.rows.push(table_track);
|
self.builder.table.rows.push(table_track);
|
||||||
|
|
||||||
let last_row = self.builder.table.rows.len();
|
let last_row = self.builder.table.rows.len();
|
||||||
if let Some(index) = self.current_row_group_index {
|
if let Some(index) = self.current_row_group_index {
|
||||||
let row_group = &mut self.builder.table.row_groups[index];
|
let row_group = &mut self.builder.table.row_groups[index];
|
||||||
row_group.track_range.end = last_row;
|
row_group.borrow_mut().track_range.end = last_row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,12 +772,13 @@ where
|
||||||
self.builder.incoming_rowspans.clear();
|
self.builder.incoming_rowspans.clear();
|
||||||
|
|
||||||
let next_row_index = self.builder.table.rows.len();
|
let next_row_index = self.builder.table.rows.len();
|
||||||
self.builder.table.row_groups.push(TableTrackGroup {
|
let row_group = ArcRefCell::new(TableTrackGroup {
|
||||||
base_fragment_info: info.into(),
|
base_fragment_info: info.into(),
|
||||||
style: info.style.clone(),
|
style: info.style.clone(),
|
||||||
group_type: internal.into(),
|
group_type: internal.into(),
|
||||||
track_range: next_row_index..next_row_index,
|
track_range: next_row_index..next_row_index,
|
||||||
});
|
});
|
||||||
|
self.builder.table.row_groups.push(row_group.clone());
|
||||||
|
|
||||||
let previous_propagated_data = self.current_propagated_data;
|
let previous_propagated_data = self.current_propagated_data;
|
||||||
self.current_propagated_data = self.current_propagated_data.union(&info.style);
|
self.current_propagated_data = self.current_propagated_data.union(&info.style);
|
||||||
|
@ -773,8 +797,9 @@ where
|
||||||
self.current_propagated_data = previous_propagated_data;
|
self.current_propagated_data = previous_propagated_data;
|
||||||
self.builder.incoming_rowspans.clear();
|
self.builder.incoming_rowspans.clear();
|
||||||
|
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::TrackGroup(
|
||||||
::std::mem::forget(box_slot)
|
row_group,
|
||||||
|
)));
|
||||||
},
|
},
|
||||||
DisplayLayoutInternal::TableRow => {
|
DisplayLayoutInternal::TableRow => {
|
||||||
self.finish_anonymous_row_if_needed();
|
self.finish_anonymous_row_if_needed();
|
||||||
|
@ -790,26 +815,23 @@ where
|
||||||
);
|
);
|
||||||
row_builder.finish();
|
row_builder.finish();
|
||||||
|
|
||||||
self.push_table_row(TableTrack {
|
let row = ArcRefCell::new(TableTrack {
|
||||||
base_fragment_info: info.into(),
|
base_fragment_info: info.into(),
|
||||||
style: info.style.clone(),
|
style: info.style.clone(),
|
||||||
group_index: self.current_row_group_index,
|
group_index: self.current_row_group_index,
|
||||||
is_anonymous: false,
|
is_anonymous: false,
|
||||||
});
|
});
|
||||||
|
self.push_table_row(row.clone());
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Track(row)));
|
||||||
::std::mem::forget(box_slot)
|
|
||||||
},
|
},
|
||||||
DisplayLayoutInternal::TableColumn => {
|
DisplayLayoutInternal::TableColumn => {
|
||||||
add_column(
|
let column = add_column(
|
||||||
&mut self.builder.table.columns,
|
&mut self.builder.table.columns,
|
||||||
info,
|
info,
|
||||||
None, /* group_index */
|
None, /* group_index */
|
||||||
false, /* is_anonymous */
|
false, /* is_anonymous */
|
||||||
);
|
);
|
||||||
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Track(column)));
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
|
||||||
::std::mem::forget(box_slot)
|
|
||||||
},
|
},
|
||||||
DisplayLayoutInternal::TableColumnGroup => {
|
DisplayLayoutInternal::TableColumnGroup => {
|
||||||
let column_group_index = self.builder.table.column_groups.len();
|
let column_group_index = self.builder.table.column_groups.len();
|
||||||
|
@ -839,14 +861,16 @@ where
|
||||||
.extend(column_group_builder.columns);
|
.extend(column_group_builder.columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.builder.table.column_groups.push(TableTrackGroup {
|
let column_group = ArcRefCell::new(TableTrackGroup {
|
||||||
base_fragment_info: info.into(),
|
base_fragment_info: info.into(),
|
||||||
style: info.style.clone(),
|
style: info.style.clone(),
|
||||||
group_type: internal.into(),
|
group_type: internal.into(),
|
||||||
track_range: first_column..self.builder.table.columns.len(),
|
track_range: first_column..self.builder.table.columns.len(),
|
||||||
});
|
});
|
||||||
|
self.builder.table.column_groups.push(column_group.clone());
|
||||||
::std::mem::forget(box_slot);
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::TrackGroup(
|
||||||
|
column_group,
|
||||||
|
)));
|
||||||
},
|
},
|
||||||
DisplayLayoutInternal::TableCaption => {
|
DisplayLayoutInternal::TableCaption => {
|
||||||
let contents = match contents.try_into() {
|
let contents = match contents.try_into() {
|
||||||
|
@ -864,17 +888,14 @@ where
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let caption = TableCaption {
|
let caption = ArcRefCell::new(TableCaption {
|
||||||
context: ArcRefCell::new(IndependentFormattingContext {
|
context: IndependentFormattingContext {
|
||||||
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
||||||
contents: IndependentFormattingContextContents::NonReplaced(contents),
|
contents: IndependentFormattingContextContents::NonReplaced(contents),
|
||||||
}),
|
},
|
||||||
};
|
});
|
||||||
|
self.builder.table.captions.push(caption.clone());
|
||||||
self.builder.table.captions.push(caption);
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Caption(caption)));
|
||||||
|
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
|
||||||
::std::mem::forget(box_slot)
|
|
||||||
},
|
},
|
||||||
DisplayLayoutInternal::TableCell => {
|
DisplayLayoutInternal::TableCell => {
|
||||||
self.current_anonymous_row_content
|
self.current_anonymous_row_content
|
||||||
|
@ -968,12 +989,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_container = builder.finish();
|
let block_container = builder.finish();
|
||||||
self.table_traversal.builder.add_cell(TableSlotCell {
|
self.table_traversal
|
||||||
|
.builder
|
||||||
|
.add_cell(ArcRefCell::new(TableSlotCell {
|
||||||
base: LayoutBoxBase::new(BaseFragmentInfo::anonymous(), anonymous_info.style),
|
base: LayoutBoxBase::new(BaseFragmentInfo::anonymous(), anonymous_info.style),
|
||||||
contents: BlockFormattingContext::from_block_container(block_container),
|
contents: BlockFormattingContext::from_block_container(block_container),
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,15 +1055,15 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
self.finish_current_anonymous_cell_if_needed();
|
self.finish_current_anonymous_cell_if_needed();
|
||||||
self.table_traversal.builder.add_cell(TableSlotCell {
|
|
||||||
|
let cell = ArcRefCell::new(TableSlotCell {
|
||||||
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
||||||
contents,
|
contents,
|
||||||
colspan,
|
colspan,
|
||||||
rowspan,
|
rowspan,
|
||||||
});
|
});
|
||||||
|
self.table_traversal.builder.add_cell(cell.clone());
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Cell(cell)));
|
||||||
::std::mem::forget(box_slot)
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
//// TODO: Properly handle other table-like elements in the middle of a row.
|
//// TODO: Properly handle other table-like elements in the middle of a row.
|
||||||
|
@ -1068,7 +1091,7 @@ where
|
||||||
|
|
||||||
struct TableColumnGroupBuilder {
|
struct TableColumnGroupBuilder {
|
||||||
column_group_index: usize,
|
column_group_index: usize,
|
||||||
columns: Vec<TableTrack>,
|
columns: Vec<ArcRefCell<TableTrack>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableColumnGroupBuilder
|
impl<'dom, Node: 'dom> TraversalHandler<'dom, Node> for TableColumnGroupBuilder
|
||||||
|
@ -1083,21 +1106,22 @@ where
|
||||||
_contents: Contents,
|
_contents: Contents,
|
||||||
box_slot: BoxSlot<'dom>,
|
box_slot: BoxSlot<'dom>,
|
||||||
) {
|
) {
|
||||||
// We are doing this until we have actually set a Box for this `BoxSlot`.
|
|
||||||
::std::mem::forget(box_slot);
|
|
||||||
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
display,
|
display,
|
||||||
DisplayGeneratingBox::LayoutInternal(DisplayLayoutInternal::TableColumn)
|
DisplayGeneratingBox::LayoutInternal(DisplayLayoutInternal::TableColumn)
|
||||||
) {
|
) {
|
||||||
|
// The BoxSlot destructor will check to ensure that it isn't empty but in this case, the
|
||||||
|
// DOM node doesn't produce any box, so explicitly skip the destructor here.
|
||||||
|
::std::mem::forget(box_slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_column(
|
let column = add_column(
|
||||||
&mut self.columns,
|
&mut self.columns,
|
||||||
info,
|
info,
|
||||||
Some(self.column_group_index),
|
Some(self.column_group_index),
|
||||||
false, /* is_anonymous */
|
false, /* is_anonymous */
|
||||||
);
|
);
|
||||||
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Track(column)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,14 +1137,12 @@ impl From<DisplayLayoutInternal> for TableTrackGroupType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_column<'dom, Node>(
|
fn add_column<'dom, Node: NodeExt<'dom>>(
|
||||||
collection: &mut Vec<TableTrack>,
|
collection: &mut Vec<ArcRefCell<TableTrack>>,
|
||||||
column_info: &NodeAndStyleInfo<Node>,
|
column_info: &NodeAndStyleInfo<Node>,
|
||||||
group_index: Option<usize>,
|
group_index: Option<usize>,
|
||||||
is_anonymous: bool,
|
is_anonymous: bool,
|
||||||
) where
|
) -> ArcRefCell<TableTrack> {
|
||||||
Node: NodeExt<'dom>,
|
|
||||||
{
|
|
||||||
let span = if column_info.pseudo_element_type.is_none() {
|
let span = if column_info.pseudo_element_type.is_none() {
|
||||||
column_info
|
column_info
|
||||||
.node
|
.node
|
||||||
|
@ -1132,13 +1154,12 @@ fn add_column<'dom, Node>(
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
|
|
||||||
collection.extend(
|
let column = ArcRefCell::new(TableTrack {
|
||||||
repeat(TableTrack {
|
|
||||||
base_fragment_info: column_info.into(),
|
base_fragment_info: column_info.into(),
|
||||||
style: column_info.style.clone(),
|
style: column_info.style.clone(),
|
||||||
group_index,
|
group_index,
|
||||||
is_anonymous,
|
is_anonymous,
|
||||||
})
|
});
|
||||||
.take(span),
|
collection.extend(repeat(column.clone()).take(span));
|
||||||
);
|
column
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::mem;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use atomic_refcell::AtomicRef;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -280,7 +281,8 @@ impl<'a> TableLayout<'a> {
|
||||||
let cell = match self.table.slots[row_index][column_index] {
|
let cell = match self.table.slots[row_index][column_index] {
|
||||||
TableSlot::Cell(ref cell) => cell,
|
TableSlot::Cell(ref cell) => cell,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
}
|
||||||
|
.borrow();
|
||||||
|
|
||||||
let layout_style = cell.layout_style();
|
let layout_style = cell.layout_style();
|
||||||
let padding = layout_style
|
let padding = layout_style
|
||||||
|
@ -393,12 +395,13 @@ impl<'a> TableLayout<'a> {
|
||||||
|
|
||||||
for column_index in 0..self.table.size.width {
|
for column_index in 0..self.table.size.width {
|
||||||
if let Some(column) = self.table.columns.get(column_index) {
|
if let Some(column) = self.table.columns.get(column_index) {
|
||||||
|
let column = column.borrow();
|
||||||
if is_length(&column.style.box_size(writing_mode).inline) {
|
if is_length(&column.style.box_size(writing_mode).inline) {
|
||||||
self.columns[column_index].constrained = true;
|
self.columns[column_index].constrained = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(column_group_index) = column.group_index {
|
if let Some(column_group_index) = column.group_index {
|
||||||
let column_group = &self.table.column_groups[column_group_index];
|
let column_group = self.table.column_groups[column_group_index].borrow();
|
||||||
if is_length(&column_group.style.box_size(writing_mode).inline) {
|
if is_length(&column_group.style.box_size(writing_mode).inline) {
|
||||||
self.columns[column_index].constrained = true;
|
self.columns[column_index].constrained = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -409,12 +412,13 @@ impl<'a> TableLayout<'a> {
|
||||||
|
|
||||||
for row_index in 0..self.table.size.height {
|
for row_index in 0..self.table.size.height {
|
||||||
if let Some(row) = self.table.rows.get(row_index) {
|
if let Some(row) = self.table.rows.get(row_index) {
|
||||||
|
let row = row.borrow();
|
||||||
if is_length(&row.style.box_size(writing_mode).block) {
|
if is_length(&row.style.box_size(writing_mode).block) {
|
||||||
self.rows[row_index].constrained = true;
|
self.rows[row_index].constrained = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(row_group_index) = row.group_index {
|
if let Some(row_group_index) = row.group_index {
|
||||||
let row_group = &self.table.row_groups[row_group_index];
|
let row_group = self.table.row_groups[row_group_index].borrow();
|
||||||
if is_length(&row_group.style.box_size(writing_mode).block) {
|
if is_length(&row_group.style.box_size(writing_mode).block) {
|
||||||
self.rows[row_index].constrained = true;
|
self.rows[row_index].constrained = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -434,7 +438,7 @@ impl<'a> TableLayout<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let rowspan_greater_than_1 = match self.table.slots[row_index][column_index] {
|
let rowspan_greater_than_1 = match self.table.slots[row_index][column_index] {
|
||||||
TableSlot::Cell(ref cell) => cell.rowspan > 1,
|
TableSlot::Cell(ref cell) => cell.borrow().rowspan > 1,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -501,7 +505,8 @@ impl<'a> TableLayout<'a> {
|
||||||
let cell = match self.table.get_slot(coords) {
|
let cell = match self.table.get_slot(coords) {
|
||||||
Some(TableSlot::Cell(cell)) => cell,
|
Some(TableSlot::Cell(cell)) => cell,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
}
|
||||||
|
.borrow();
|
||||||
|
|
||||||
if cell.colspan != 1 {
|
if cell.colspan != 1 {
|
||||||
colspan_cell_constraints.push(ColspanToDistribute {
|
colspan_cell_constraints.push(ColspanToDistribute {
|
||||||
|
@ -708,8 +713,9 @@ impl<'a> TableLayout<'a> {
|
||||||
.captions
|
.captions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|caption| {
|
.map(|caption| {
|
||||||
let context = caption.context.borrow();
|
caption
|
||||||
context
|
.borrow()
|
||||||
|
.context
|
||||||
.outer_inline_content_sizes(
|
.outer_inline_content_sizes(
|
||||||
layout_context,
|
layout_context,
|
||||||
&containing_block,
|
&containing_block,
|
||||||
|
@ -1075,9 +1081,11 @@ impl<'a> TableLayout<'a> {
|
||||||
let collect_for_nearest_positioned_ancestor = parent_positioning_context
|
let collect_for_nearest_positioned_ancestor = parent_positioning_context
|
||||||
.collects_for_nearest_positioned_ancestor() ||
|
.collects_for_nearest_positioned_ancestor() ||
|
||||||
self.table.rows.get(row_index).is_some_and(|row| {
|
self.table.rows.get(row_index).is_some_and(|row| {
|
||||||
|
let row = row.borrow();
|
||||||
let row_group_collects_for_nearest_positioned_ancestor =
|
let row_group_collects_for_nearest_positioned_ancestor =
|
||||||
row.group_index.is_some_and(|group_index| {
|
row.group_index.is_some_and(|group_index| {
|
||||||
self.table.row_groups[group_index]
|
self.table.row_groups[group_index]
|
||||||
|
.borrow()
|
||||||
.style
|
.style
|
||||||
.establishes_containing_block_for_absolute_descendants(
|
.establishes_containing_block_for_absolute_descendants(
|
||||||
FragmentFlags::empty(),
|
FragmentFlags::empty(),
|
||||||
|
@ -1098,6 +1106,7 @@ impl<'a> TableLayout<'a> {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let cell = cell.borrow();
|
||||||
let area = LogicalSides {
|
let area = LogicalSides {
|
||||||
inline_start: column_index,
|
inline_start: column_index,
|
||||||
inline_end: column_index + cell.colspan,
|
inline_end: column_index + cell.colspan,
|
||||||
|
@ -1192,6 +1201,7 @@ impl<'a> TableLayout<'a> {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let cell = cell.borrow();
|
||||||
let outer_block_size = layout.outer_block_size();
|
let outer_block_size = layout.outer_block_size();
|
||||||
if cell.rowspan == 1 {
|
if cell.rowspan == 1 {
|
||||||
max_row_height.max_assign(outer_block_size);
|
max_row_height.max_assign(outer_block_size);
|
||||||
|
@ -1251,7 +1261,7 @@ impl<'a> TableLayout<'a> {
|
||||||
|
|
||||||
let cell_measure = &self.cell_measures[row_index][column_index].block;
|
let cell_measure = &self.cell_measures[row_index][column_index].block;
|
||||||
let cell = match self.table.slots[row_index][column_index] {
|
let cell = match self.table.slots[row_index][column_index] {
|
||||||
TableSlot::Cell(ref cell) if cell.rowspan > 1 => cell,
|
TableSlot::Cell(ref cell) if cell.borrow().rowspan > 1 => cell,
|
||||||
TableSlot::Cell(_) => {
|
TableSlot::Cell(_) => {
|
||||||
// If this is an originating cell, that isn't spanning, then we make sure the row is
|
// If this is an originating cell, that isn't spanning, then we make sure the row is
|
||||||
// at least big enough to hold the cell.
|
// at least big enough to hold the cell.
|
||||||
|
@ -1263,7 +1273,7 @@ impl<'a> TableLayout<'a> {
|
||||||
|
|
||||||
cells_to_distribute.push(RowspanToDistribute {
|
cells_to_distribute.push(RowspanToDistribute {
|
||||||
coordinates: TableSlotCoordinates::new(column_index, row_index),
|
coordinates: TableSlotCoordinates::new(column_index, row_index),
|
||||||
cell,
|
cell: cell.borrow(),
|
||||||
measure: cell_measure,
|
measure: cell_measure,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1491,8 +1501,7 @@ impl<'a> TableLayout<'a> {
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
parent_positioning_context: &mut PositioningContext,
|
parent_positioning_context: &mut PositioningContext,
|
||||||
) -> BoxFragment {
|
) -> BoxFragment {
|
||||||
let context = caption.context.borrow();
|
let mut positioning_context = PositioningContext::new_for_style(caption.context.style());
|
||||||
let mut positioning_context = PositioningContext::new_for_style(context.style());
|
|
||||||
let containing_block = &ContainingBlock {
|
let containing_block = &ContainingBlock {
|
||||||
size: ContainingBlockSize {
|
size: ContainingBlockSize {
|
||||||
inline: self.table_width + self.pbm.padding_border_sums.inline,
|
inline: self.table_width + self.pbm.padding_border_sums.inline,
|
||||||
|
@ -1506,7 +1515,7 @@ impl<'a> TableLayout<'a> {
|
||||||
// stretch block size. https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
|
// stretch block size. https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
|
||||||
let ignore_block_margins_for_stretch = LogicalSides1D::new(false, false);
|
let ignore_block_margins_for_stretch = LogicalSides1D::new(false, false);
|
||||||
|
|
||||||
let mut box_fragment = context.layout_in_flow_block_level(
|
let mut box_fragment = caption.context.layout_in_flow_block_level(
|
||||||
layout_context,
|
layout_context,
|
||||||
positioning_context
|
positioning_context
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -1596,13 +1605,14 @@ impl<'a> TableLayout<'a> {
|
||||||
table_layout
|
table_layout
|
||||||
.fragments
|
.fragments
|
||||||
.extend(self.table.captions.iter().filter_map(|caption| {
|
.extend(self.table.captions.iter().filter_map(|caption| {
|
||||||
if caption.context.borrow().style().clone_caption_side() != CaptionSide::Top {
|
let caption = caption.borrow();
|
||||||
|
if caption.context.style().clone_caption_side() != CaptionSide::Top {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let original_positioning_context_length = positioning_context.len();
|
let original_positioning_context_length = positioning_context.len();
|
||||||
let mut caption_fragment =
|
let mut caption_fragment =
|
||||||
self.layout_caption(caption, layout_context, positioning_context);
|
self.layout_caption(&caption, layout_context, positioning_context);
|
||||||
|
|
||||||
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
||||||
// for the table children and only then convert the result to physical geometry.
|
// for the table children and only then convert the result to physical geometry.
|
||||||
|
@ -1698,13 +1708,14 @@ impl<'a> TableLayout<'a> {
|
||||||
table_layout
|
table_layout
|
||||||
.fragments
|
.fragments
|
||||||
.extend(self.table.captions.iter().filter_map(|caption| {
|
.extend(self.table.captions.iter().filter_map(|caption| {
|
||||||
if caption.context.borrow().style().clone_caption_side() != CaptionSide::Bottom {
|
let caption = caption.borrow();
|
||||||
|
if caption.context.style().clone_caption_side() != CaptionSide::Bottom {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let original_positioning_context_length = positioning_context.len();
|
let original_positioning_context_length = positioning_context.len();
|
||||||
let mut caption_fragment =
|
let mut caption_fragment =
|
||||||
self.layout_caption(caption, layout_context, positioning_context);
|
self.layout_caption(&caption, layout_context, positioning_context);
|
||||||
|
|
||||||
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
// The caption is not placed yet. Construct a rectangle for it in the adjusted containing block
|
||||||
// for the table children and only then convert the result to physical geometry.
|
// for the table children and only then convert the result to physical geometry.
|
||||||
|
@ -1820,9 +1831,9 @@ impl<'a> TableLayout<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let table_row = &self.table.rows[row_index];
|
let table_row = self.table.rows[row_index].borrow();
|
||||||
let mut row_fragment_layout = RowFragmentLayout::new(
|
let mut row_fragment_layout = RowFragmentLayout::new(
|
||||||
table_row,
|
&table_row,
|
||||||
row_index,
|
row_index,
|
||||||
&table_and_track_dimensions,
|
&table_and_track_dimensions,
|
||||||
&self.table.style,
|
&self.table.style,
|
||||||
|
@ -1845,7 +1856,7 @@ impl<'a> TableLayout<'a> {
|
||||||
// Then, create a new RowGroupFragmentLayout for the current and potentially subsequent rows.
|
// Then, create a new RowGroupFragmentLayout for the current and potentially subsequent rows.
|
||||||
if let Some(new_group_index) = table_row.group_index {
|
if let Some(new_group_index) = table_row.group_index {
|
||||||
row_group_fragment_layout = Some(RowGroupFragmentLayout::new(
|
row_group_fragment_layout = Some(RowGroupFragmentLayout::new(
|
||||||
&self.table.row_groups[new_group_index],
|
&self.table.row_groups[new_group_index].borrow(),
|
||||||
new_group_index,
|
new_group_index,
|
||||||
&table_and_track_dimensions,
|
&table_and_track_dimensions,
|
||||||
));
|
));
|
||||||
|
@ -1960,25 +1971,28 @@ impl<'a> TableLayout<'a> {
|
||||||
let Some(row) = &self.table.rows.get(row_index) else {
|
let Some(row) = &self.table.rows.get(row_index) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let row = row.borrow();
|
||||||
if row.style.get_inherited_box().visibility == Visibility::Collapse {
|
if row.style.get_inherited_box().visibility == Visibility::Collapse {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let row_group = match row.group_index {
|
let row_group = match row.group_index {
|
||||||
Some(group_index) => &self.table.row_groups[group_index],
|
Some(group_index) => self.table.row_groups[group_index].borrow(),
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
row_group.style.get_inherited_box().visibility == Visibility::Collapse
|
row_group.style.get_inherited_box().visibility == Visibility::Collapse
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_column_collapsed(&self, column_index: usize) -> bool {
|
fn is_column_collapsed(&self, column_index: usize) -> bool {
|
||||||
let Some(col) = &self.table.columns.get(column_index) else {
|
let Some(column) = &self.table.columns.get(column_index) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if col.style.get_inherited_box().visibility == Visibility::Collapse {
|
let column = column.borrow();
|
||||||
|
if column.style.get_inherited_box().visibility == Visibility::Collapse {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let col_group = match col.group_index {
|
let col_group = match column.group_index {
|
||||||
Some(group_index) => &self.table.column_groups[group_index],
|
Some(group_index) => self.table.column_groups[group_index].borrow(),
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
col_group.style.get_inherited_box().visibility == Visibility::Collapse
|
col_group.style.get_inherited_box().visibility == Visibility::Collapse
|
||||||
|
@ -2017,7 +2031,8 @@ impl<'a> TableLayout<'a> {
|
||||||
warn!("Did not find a non-spanned cell at index with layout.");
|
warn!("Did not find a non-spanned cell at index with layout.");
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
.borrow();
|
||||||
|
|
||||||
// If this cell has baseline alignment, it can adjust the table's overall baseline.
|
// If this cell has baseline alignment, it can adjust the table's overall baseline.
|
||||||
let row_block_offset = row_fragment_layout.rect.start_corner.block;
|
let row_block_offset = row_fragment_layout.rect.start_corner.block;
|
||||||
|
@ -2067,16 +2082,18 @@ impl<'a> TableLayout<'a> {
|
||||||
|
|
||||||
let column = self.table.columns.get(column_index);
|
let column = self.table.columns.get(column_index);
|
||||||
let column_group = column
|
let column_group = column
|
||||||
.and_then(|column| column.group_index)
|
.and_then(|column| column.borrow().group_index)
|
||||||
.and_then(|index| self.table.column_groups.get(index));
|
.and_then(|index| self.table.column_groups.get(index));
|
||||||
if let Some(column_group) = column_group {
|
if let Some(column_group) = column_group {
|
||||||
let rect = make_relative_to_row_start(dimensions.get_column_group_rect(column_group));
|
let column_group = column_group.borrow();
|
||||||
|
let rect = make_relative_to_row_start(dimensions.get_column_group_rect(&column_group));
|
||||||
fragment.add_extra_background(ExtraBackground {
|
fragment.add_extra_background(ExtraBackground {
|
||||||
style: column_group.style.clone(),
|
style: column_group.style.clone(),
|
||||||
rect,
|
rect,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if let Some(column) = column {
|
if let Some(column) = column {
|
||||||
|
let column = column.borrow();
|
||||||
if !column.is_anonymous {
|
if !column.is_anonymous {
|
||||||
let rect = make_relative_to_row_start(dimensions.get_column_rect(column_index));
|
let rect = make_relative_to_row_start(dimensions.get_column_rect(column_index));
|
||||||
fragment.add_extra_background(ExtraBackground {
|
fragment.add_extra_background(ExtraBackground {
|
||||||
|
@ -2087,16 +2104,18 @@ impl<'a> TableLayout<'a> {
|
||||||
}
|
}
|
||||||
let row = self.table.rows.get(row_index);
|
let row = self.table.rows.get(row_index);
|
||||||
let row_group = row
|
let row_group = row
|
||||||
.and_then(|row| row.group_index)
|
.and_then(|row| row.borrow().group_index)
|
||||||
.and_then(|index| self.table.row_groups.get(index));
|
.and_then(|index| self.table.row_groups.get(index));
|
||||||
if let Some(row_group) = row_group {
|
if let Some(row_group) = row_group {
|
||||||
let rect = make_relative_to_row_start(dimensions.get_row_group_rect(row_group));
|
let rect =
|
||||||
|
make_relative_to_row_start(dimensions.get_row_group_rect(&row_group.borrow()));
|
||||||
fragment.add_extra_background(ExtraBackground {
|
fragment.add_extra_background(ExtraBackground {
|
||||||
style: row_group.style.clone(),
|
style: row_group.borrow().style.clone(),
|
||||||
rect,
|
rect,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if let Some(row) = row {
|
if let Some(row) = row {
|
||||||
|
let row = row.borrow();
|
||||||
let rect = make_relative_to_row_start(row_fragment_layout.rect);
|
let rect = make_relative_to_row_start(row_fragment_layout.rect);
|
||||||
fragment.add_extra_background(ExtraBackground {
|
fragment.add_extra_background(ExtraBackground {
|
||||||
style: row.style.clone(),
|
style: row.style.clone(),
|
||||||
|
@ -2114,11 +2133,12 @@ impl<'a> TableLayout<'a> {
|
||||||
fragments: &mut Vec<Fragment>,
|
fragments: &mut Vec<Fragment>,
|
||||||
) {
|
) {
|
||||||
for column_group in self.table.column_groups.iter() {
|
for column_group in self.table.column_groups.iter() {
|
||||||
|
let column_group = column_group.borrow();
|
||||||
if !column_group.is_empty() {
|
if !column_group.is_empty() {
|
||||||
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
||||||
column_group.base_fragment_info,
|
column_group.base_fragment_info,
|
||||||
dimensions
|
dimensions
|
||||||
.get_column_group_rect(column_group)
|
.get_column_group_rect(&column_group)
|
||||||
.as_physical(None),
|
.as_physical(None),
|
||||||
column_group.style.clone(),
|
column_group.style.clone(),
|
||||||
)));
|
)));
|
||||||
|
@ -2126,6 +2146,7 @@ impl<'a> TableLayout<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (column_index, column) in self.table.columns.iter().enumerate() {
|
for (column_index, column) in self.table.columns.iter().enumerate() {
|
||||||
|
let column = column.borrow();
|
||||||
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
|
||||||
column.base_fragment_info,
|
column.base_fragment_info,
|
||||||
dimensions.get_column_rect(column_index).as_physical(None),
|
dimensions.get_column_rect(column_index).as_physical(None),
|
||||||
|
@ -2190,7 +2211,8 @@ impl<'a> TableLayout<'a> {
|
||||||
let cell = match self.table.slots[row_index][column_index] {
|
let cell = match self.table.slots[row_index][column_index] {
|
||||||
TableSlot::Cell(ref cell) => cell,
|
TableSlot::Cell(ref cell) => cell,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
}
|
||||||
|
.borrow();
|
||||||
let block_range = row_index..row_index + cell.rowspan;
|
let block_range = row_index..row_index + cell.rowspan;
|
||||||
let inline_range = column_index..column_index + cell.colspan;
|
let inline_range = column_index..column_index + cell.colspan;
|
||||||
hide_inner_borders(&mut collapsed_borders, &block_range, &inline_range);
|
hide_inner_borders(&mut collapsed_borders, &block_range, &inline_range);
|
||||||
|
@ -2203,6 +2225,7 @@ impl<'a> TableLayout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (row_index, row) in self.table.rows.iter().enumerate() {
|
for (row_index, row) in self.table.rows.iter().enumerate() {
|
||||||
|
let row = row.borrow();
|
||||||
apply_border(
|
apply_border(
|
||||||
&mut collapsed_borders,
|
&mut collapsed_borders,
|
||||||
&row.layout_style(),
|
&row.layout_style(),
|
||||||
|
@ -2211,6 +2234,7 @@ impl<'a> TableLayout<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for row_group in &self.table.row_groups {
|
for row_group in &self.table.row_groups {
|
||||||
|
let row_group = row_group.borrow();
|
||||||
apply_border(
|
apply_border(
|
||||||
&mut collapsed_borders,
|
&mut collapsed_borders,
|
||||||
&row_group.layout_style(),
|
&row_group.layout_style(),
|
||||||
|
@ -2219,6 +2243,7 @@ impl<'a> TableLayout<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (column_index, column) in self.table.columns.iter().enumerate() {
|
for (column_index, column) in self.table.columns.iter().enumerate() {
|
||||||
|
let column = column.borrow();
|
||||||
apply_border(
|
apply_border(
|
||||||
&mut collapsed_borders,
|
&mut collapsed_borders,
|
||||||
&column.layout_style(),
|
&column.layout_style(),
|
||||||
|
@ -2227,6 +2252,7 @@ impl<'a> TableLayout<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for column_group in &self.table.column_groups {
|
for column_group in &self.table.column_groups {
|
||||||
|
let column_group = column_group.borrow();
|
||||||
apply_border(
|
apply_border(
|
||||||
&mut collapsed_borders,
|
&mut collapsed_borders,
|
||||||
&column_group.layout_style(),
|
&column_group.layout_style(),
|
||||||
|
@ -2599,7 +2625,8 @@ impl Table {
|
||||||
let column = match self.columns.get(column_index) {
|
let column = match self.columns.get(column_index) {
|
||||||
Some(column) => column,
|
Some(column) => column,
|
||||||
None => return CellOrTrackMeasure::zero(),
|
None => return CellOrTrackMeasure::zero(),
|
||||||
};
|
}
|
||||||
|
.borrow();
|
||||||
|
|
||||||
let CellOrColumnOuterSizes {
|
let CellOrColumnOuterSizes {
|
||||||
preferred: preferred_size,
|
preferred: preferred_size,
|
||||||
|
@ -2644,6 +2671,7 @@ impl Table {
|
||||||
// In the block axis, the min-content and max-content sizes are the same
|
// In the block axis, the min-content and max-content sizes are the same
|
||||||
// (except for new layout boxes like grid and flex containers). Note that
|
// (except for new layout boxes like grid and flex containers). Note that
|
||||||
// other browsers don't seem to use the min and max sizing properties here.
|
// other browsers don't seem to use the min and max sizing properties here.
|
||||||
|
let row = row.borrow();
|
||||||
let size = row.style.box_size(writing_mode);
|
let size = row.style.box_size(writing_mode);
|
||||||
let max_size = row.style.max_box_size(writing_mode);
|
let max_size = row.style.max_box_size(writing_mode);
|
||||||
let percentage_contribution = get_size_percentage_contribution(&size, &max_size);
|
let percentage_contribution = get_size_percentage_contribution(&size, &max_size);
|
||||||
|
@ -2979,7 +3007,7 @@ impl CellOrColumnOuterSizes {
|
||||||
|
|
||||||
struct RowspanToDistribute<'a> {
|
struct RowspanToDistribute<'a> {
|
||||||
coordinates: TableSlotCoordinates,
|
coordinates: TableSlotCoordinates,
|
||||||
cell: &'a TableSlotCell,
|
cell: AtomicRef<'a, TableSlotCell>,
|
||||||
measure: &'a CellOrTrackMeasure,
|
measure: &'a CellOrTrackMeasure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ mod layout;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use atomic_refcell::AtomicRef;
|
||||||
pub(crate) use construct::AnonymousTableContent;
|
pub(crate) use construct::AnonymousTableContent;
|
||||||
pub use construct::TableBuilder;
|
pub use construct::TableBuilder;
|
||||||
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
|
use euclid::{Point2D, Size2D, UnknownUnit, Vector2D};
|
||||||
|
@ -107,20 +108,20 @@ pub struct Table {
|
||||||
grid_base_fragment_info: BaseFragmentInfo,
|
grid_base_fragment_info: BaseFragmentInfo,
|
||||||
|
|
||||||
/// The captions for this table.
|
/// The captions for this table.
|
||||||
pub captions: Vec<TableCaption>,
|
pub captions: Vec<ArcRefCell<TableCaption>>,
|
||||||
|
|
||||||
/// The column groups for this table.
|
/// The column groups for this table.
|
||||||
pub column_groups: Vec<TableTrackGroup>,
|
pub column_groups: Vec<ArcRefCell<TableTrackGroup>>,
|
||||||
|
|
||||||
/// The columns of this table defined by `<colgroup> | display: table-column-group`
|
/// The columns of this table defined by `<colgroup> | display: table-column-group`
|
||||||
/// and `<col> | display: table-column` elements as well as `display: table-column`.
|
/// and `<col> | display: table-column` elements as well as `display: table-column`.
|
||||||
pub columns: Vec<TableTrack>,
|
pub columns: Vec<ArcRefCell<TableTrack>>,
|
||||||
|
|
||||||
/// The rows groups for this table defined by `<tbody>`, `<thead>`, and `<tfoot>`.
|
/// The rows groups for this table defined by `<tbody>`, `<thead>`, and `<tfoot>`.
|
||||||
pub row_groups: Vec<TableTrackGroup>,
|
pub row_groups: Vec<ArcRefCell<TableTrackGroup>>,
|
||||||
|
|
||||||
/// The rows of this table defined by `<tr>` or `display: table-row` elements.
|
/// The rows of this table defined by `<tr>` or `display: table-row` elements.
|
||||||
pub rows: Vec<TableTrack>,
|
pub rows: Vec<ArcRefCell<TableTrack>>,
|
||||||
|
|
||||||
/// The content of the slots of this table.
|
/// The content of the slots of this table.
|
||||||
pub slots: Vec<Vec<TableSlot>>,
|
pub slots: Vec<Vec<TableSlot>>,
|
||||||
|
@ -175,11 +176,14 @@ impl Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_first_cell(&self, coords: TableSlotCoordinates) -> Option<&TableSlotCell> {
|
fn resolve_first_cell(
|
||||||
|
&self,
|
||||||
|
coords: TableSlotCoordinates,
|
||||||
|
) -> Option<AtomicRef<'_, TableSlotCell>> {
|
||||||
let resolved_coords = self.resolve_first_cell_coords(coords)?;
|
let resolved_coords = self.resolve_first_cell_coords(coords)?;
|
||||||
let slot = self.get_slot(resolved_coords);
|
let slot = self.get_slot(resolved_coords);
|
||||||
match slot {
|
match slot {
|
||||||
Some(TableSlot::Cell(cell)) => Some(cell),
|
Some(TableSlot::Cell(cell)) => Some(cell.borrow()),
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
"Spanned slot should not point to an empty cell or another spanned slot."
|
"Spanned slot should not point to an empty cell or another spanned slot."
|
||||||
),
|
),
|
||||||
|
@ -234,7 +238,7 @@ impl TableSlotCell {
|
||||||
/// In case of table model errors, it may be multiple references
|
/// In case of table model errors, it may be multiple references
|
||||||
pub enum TableSlot {
|
pub enum TableSlot {
|
||||||
/// A table cell, with a colspan and a rowspan.
|
/// A table cell, with a colspan and a rowspan.
|
||||||
Cell(TableSlotCell),
|
Cell(ArcRefCell<TableSlotCell>),
|
||||||
|
|
||||||
/// This slot is spanned by one or more multiple cells earlier in the table, which are
|
/// This slot is spanned by one or more multiple cells earlier in the table, which are
|
||||||
/// found at the given negative coordinate offsets. The vector is in the order of most
|
/// found at the given negative coordinate offsets. The vector is in the order of most
|
||||||
|
@ -317,7 +321,7 @@ impl TableTrackGroup {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TableCaption {
|
pub struct TableCaption {
|
||||||
/// The contents of this cell, with its own layout.
|
/// The contents of this cell, with its own layout.
|
||||||
context: ArcRefCell<IndependentFormattingContext>,
|
context: IndependentFormattingContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A calculated collapsed border.
|
/// A calculated collapsed border.
|
||||||
|
@ -340,3 +344,30 @@ pub(crate) struct TableLayoutStyle<'a> {
|
||||||
table: &'a Table,
|
table: &'a Table,
|
||||||
layout: Option<&'a TableLayout<'a>>,
|
layout: Option<&'a TableLayout<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Table parts that are stored in the DOM. This is used in order to map from
|
||||||
|
/// the DOM to the box tree and will eventually be important for incremental
|
||||||
|
/// layout.
|
||||||
|
pub(crate) enum TableLevelBox {
|
||||||
|
Caption(ArcRefCell<TableCaption>),
|
||||||
|
Cell(ArcRefCell<TableSlotCell>),
|
||||||
|
#[allow(dead_code)]
|
||||||
|
TrackGroup(ArcRefCell<TableTrackGroup>),
|
||||||
|
#[allow(dead_code)]
|
||||||
|
Track(ArcRefCell<TableTrack>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableLevelBox {
|
||||||
|
pub(crate) fn invalidate_cached_fragment(&self) {
|
||||||
|
match self {
|
||||||
|
TableLevelBox::Caption(caption) => {
|
||||||
|
caption.borrow().context.base.invalidate_cached_fragment();
|
||||||
|
},
|
||||||
|
TableLevelBox::Cell(cell) => {
|
||||||
|
cell.borrow().base.invalidate_cached_fragment();
|
||||||
|
},
|
||||||
|
TableLevelBox::TrackGroup(..) => {},
|
||||||
|
TableLevelBox::Track(..) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
mod tables {
|
mod tables {
|
||||||
use euclid::Vector2D;
|
use euclid::Vector2D;
|
||||||
|
use layout_2020::ArcRefCell;
|
||||||
use layout_2020::table::{Table, TableBuilder, TableSlot, TableSlotCell, TableSlotOffset};
|
use layout_2020::table::{Table, TableBuilder, TableSlot, TableSlotCell, TableSlotOffset};
|
||||||
|
|
||||||
fn row_lengths(table: &Table) -> Vec<usize> {
|
fn row_lengths(table: &Table) -> Vec<usize> {
|
||||||
|
@ -14,7 +15,7 @@ mod tables {
|
||||||
|
|
||||||
fn slot_is_cell_with_id(slot: &TableSlot, id: usize) -> bool {
|
fn slot_is_cell_with_id(slot: &TableSlot, id: usize) -> bool {
|
||||||
match slot {
|
match slot {
|
||||||
TableSlot::Cell(cell) if cell.node_id() == id => true,
|
TableSlot::Cell(cell) if cell.borrow().node_id() == id => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,13 +52,13 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(4, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(4, 1, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
let table = table_builder.finish();
|
let table = table_builder.finish();
|
||||||
|
@ -74,13 +75,13 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 1, 2));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 1, 2)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(4, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(4, 1, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
let table = table_builder.finish();
|
let table = table_builder.finish();
|
||||||
|
@ -103,21 +104,21 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 3, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 3, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 1, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(4, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(4, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(5, 3, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(5, 3, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(6, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(6, 1, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(7, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(7, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(8, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(8, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(9, 3, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(9, 3, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
let table = table_builder.finish();
|
let table = table_builder.finish();
|
||||||
|
@ -165,13 +166,13 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 1, 2));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 1, 2)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(4, 3, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(4, 3, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
let table = table_builder.finish();
|
let table = table_builder.finish();
|
||||||
|
@ -197,9 +198,9 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 1, 0));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 1, 0)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
|
@ -235,12 +236,12 @@ mod tables {
|
||||||
let mut table_builder = TableBuilder::new_for_tests();
|
let mut table_builder = TableBuilder::new_for_tests();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(1, 1, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(1, 1, 1)));
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(2, 1, 30));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(2, 1, 30)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
table_builder.start_row();
|
table_builder.start_row();
|
||||||
table_builder.add_cell(TableSlotCell::mock_for_testing(3, 2, 1));
|
table_builder.add_cell(ArcRefCell::new(TableSlotCell::mock_for_testing(3, 2, 1)));
|
||||||
table_builder.end_row();
|
table_builder.end_row();
|
||||||
|
|
||||||
assert_eq!(table_builder.incoming_rowspans, vec![0, 28]);
|
assert_eq!(table_builder.incoming_rowspans, vec![0, 28]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue