mirror of
https://github.com/servo/servo.git
synced 2025-07-16 03:43:38 +01:00
layout: Add incremental box tree construction for table cell (#37850)
This change extends incremental box tree updates to table cells. In addition, for simplicity this refactors `BoxSlot::take_layout_box()` into `BoxSlot::take_layout_box_if_undamaged()`. Testing: This should not change observable behavior and is thus covered by existing WPT tests. Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
06cc4bdae7
commit
d33d057763
2 changed files with 54 additions and 45 deletions
|
@ -181,7 +181,10 @@ impl BoxSlot<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn take_layout_box(&self) -> Option<LayoutBox> {
|
pub(crate) fn take_layout_box_if_undamaged(&self, damage: LayoutDamage) -> Option<LayoutBox> {
|
||||||
|
if damage.has_box_damage() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
self.slot.as_ref().and_then(|slot| slot.borrow_mut().take())
|
self.slot.as_ref().and_then(|slot| slot.borrow_mut().take())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -855,14 +855,11 @@ impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> {
|
||||||
unreachable!("Replaced should not have a LayoutInternal display type.");
|
unreachable!("Replaced should not have a LayoutInternal display type.");
|
||||||
};
|
};
|
||||||
|
|
||||||
let old_caption = (!info.damage.has_box_damage())
|
let old_box = box_slot.take_layout_box_if_undamaged(info.damage);
|
||||||
.then(|| match box_slot.take_layout_box() {
|
let old_caption = old_box.and_then(|layout_box| match layout_box {
|
||||||
Some(LayoutBox::TableLevelBox(TableLevelBox::Caption(caption))) => {
|
LayoutBox::TableLevelBox(TableLevelBox::Caption(caption)) => Some(caption),
|
||||||
Some(caption)
|
_ => None,
|
||||||
},
|
});
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.flatten();
|
|
||||||
|
|
||||||
let caption = old_caption.unwrap_or_else(|| {
|
let caption = old_caption.unwrap_or_else(|| {
|
||||||
let contents = IndependentNonReplacedContents::Flow(
|
let contents = IndependentNonReplacedContents::Flow(
|
||||||
|
@ -1006,45 +1003,54 @@ impl<'dom> TraversalHandler<'dom> for TableRowBuilder<'_, '_, 'dom, '_> {
|
||||||
match display {
|
match display {
|
||||||
DisplayGeneratingBox::LayoutInternal(internal) => match internal {
|
DisplayGeneratingBox::LayoutInternal(internal) => match internal {
|
||||||
DisplayLayoutInternal::TableCell => {
|
DisplayLayoutInternal::TableCell => {
|
||||||
// This value will already have filtered out rowspan=0
|
|
||||||
// in quirks mode, so we don't have to worry about that.
|
|
||||||
let (rowspan, colspan) = if info.pseudo_element_type.is_none() {
|
|
||||||
let node = info.node.to_threadsafe();
|
|
||||||
let rowspan = node.get_rowspan().unwrap_or(1) as usize;
|
|
||||||
let colspan = node.get_colspan().unwrap_or(1) as usize;
|
|
||||||
|
|
||||||
// The HTML specification clamps value of `rowspan` to [0, 65534] and
|
|
||||||
// `colspan` to [1, 1000].
|
|
||||||
assert!((1..=1000).contains(&colspan));
|
|
||||||
assert!((0..=65534).contains(&rowspan));
|
|
||||||
|
|
||||||
(rowspan, colspan)
|
|
||||||
} else {
|
|
||||||
(1, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
let propagated_data =
|
|
||||||
self.propagated_data.disallowing_percentage_table_columns();
|
|
||||||
let Contents::NonReplaced(non_replaced_contents) = contents else {
|
|
||||||
unreachable!("Replaced should not have a LayoutInternal display type.");
|
|
||||||
};
|
|
||||||
|
|
||||||
let contents = BlockFormattingContext::construct(
|
|
||||||
self.table_traversal.context,
|
|
||||||
info,
|
|
||||||
non_replaced_contents,
|
|
||||||
propagated_data,
|
|
||||||
false, /* is_list_item */
|
|
||||||
);
|
|
||||||
|
|
||||||
self.finish_current_anonymous_cell_if_needed();
|
self.finish_current_anonymous_cell_if_needed();
|
||||||
|
|
||||||
let cell = ArcRefCell::new(TableSlotCell {
|
let old_box = box_slot.take_layout_box_if_undamaged(info.damage);
|
||||||
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
let old_cell = old_box.and_then(|layout_box| match layout_box {
|
||||||
contents,
|
LayoutBox::TableLevelBox(TableLevelBox::Cell(cell)) => Some(cell),
|
||||||
colspan,
|
_ => None,
|
||||||
rowspan,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let cell = old_cell.unwrap_or_else(|| {
|
||||||
|
// This value will already have filtered out rowspan=0
|
||||||
|
// in quirks mode, so we don't have to worry about that.
|
||||||
|
let (rowspan, colspan) = if info.pseudo_element_type.is_none() {
|
||||||
|
let node = info.node.to_threadsafe();
|
||||||
|
let rowspan = node.get_rowspan().unwrap_or(1) as usize;
|
||||||
|
let colspan = node.get_colspan().unwrap_or(1) as usize;
|
||||||
|
|
||||||
|
// The HTML specification clamps value of `rowspan` to [0, 65534] and
|
||||||
|
// `colspan` to [1, 1000].
|
||||||
|
assert!((1..=1000).contains(&colspan));
|
||||||
|
assert!((0..=65534).contains(&rowspan));
|
||||||
|
|
||||||
|
(rowspan, colspan)
|
||||||
|
} else {
|
||||||
|
(1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let propagated_data =
|
||||||
|
self.propagated_data.disallowing_percentage_table_columns();
|
||||||
|
let Contents::NonReplaced(non_replaced_contents) = contents else {
|
||||||
|
unreachable!("Replaced should not have a LayoutInternal display type.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let contents = BlockFormattingContext::construct(
|
||||||
|
self.table_traversal.context,
|
||||||
|
info,
|
||||||
|
non_replaced_contents,
|
||||||
|
propagated_data,
|
||||||
|
false, /* is_list_item */
|
||||||
|
);
|
||||||
|
|
||||||
|
ArcRefCell::new(TableSlotCell {
|
||||||
|
base: LayoutBoxBase::new(info.into(), info.style.clone()),
|
||||||
|
contents,
|
||||||
|
colspan,
|
||||||
|
rowspan,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
self.table_traversal.builder.add_cell(cell.clone());
|
self.table_traversal.builder.add_cell(cell.clone());
|
||||||
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Cell(cell)));
|
box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::Cell(cell)));
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue