diff options
Diffstat (limited to 'components/layout_2020/table/mod.rs')
-rw-r--r-- | components/layout_2020/table/mod.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs new file mode 100644 index 00000000000..a228ccc6907 --- /dev/null +++ b/components/layout_2020/table/mod.rs @@ -0,0 +1,117 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Table layout. +//! See https://html.spec.whatwg.org/multipage/table-processing-model. + +mod construct; + +pub use construct::TableBuilder; +use euclid::{Point2D, UnknownUnit, Vector2D}; +use serde::Serialize; +use style::values::computed::Length; + +use super::flow::BlockFormattingContext; +use crate::context::LayoutContext; +use crate::flow::BlockContainer; +use crate::formatting_contexts::IndependentLayout; +use crate::positioned::PositioningContext; +use crate::sizing::ContentSizes; +use crate::ContainingBlock; + +#[derive(Debug, Default, Serialize)] +pub struct Table { + pub slots: Vec<Vec<TableSlot>>, +} + +impl Table { + pub(crate) fn inline_content_sizes(&self) -> ContentSizes { + ContentSizes::zero() + } + + pub(crate) fn layout( + &self, + _layout_context: &LayoutContext, + _positioning_context: &mut PositioningContext, + _containing_block: &ContainingBlock, + ) -> IndependentLayout { + IndependentLayout { + fragments: Vec::new(), + content_block_size: Length::new(0.), + } + } +} + +type TableSlotCoordinates = Point2D<usize, UnknownUnit>; +pub type TableSlotOffset = Vector2D<usize, UnknownUnit>; + +#[derive(Debug, Serialize)] +pub struct TableSlotCell { + /// The contents of this cell, with its own layout. + contents: BlockFormattingContext, + + /// Number of columns that the cell is to span. Must be greater than zero. + colspan: usize, + + /// Number of rows that the cell is to span. Zero means that the cell is to span all + /// the remaining rows in the row group. + rowspan: usize, + + // An id used for testing purposes. + pub id: u8, +} + +impl TableSlotCell { + pub fn mock_for_testing(id: u8, colspan: usize, rowspan: usize) -> Self { + Self { + contents: BlockFormattingContext { + contents: BlockContainer::BlockLevelBoxes(Vec::new()), + contains_floats: false, + }, + colspan, + rowspan, + id, + } + } +} + +#[derive(Serialize)] +/// A single table slot. It may be an actual cell, or a reference +/// to a previous cell that is spanned here +/// +/// In case of table model errors, it may be multiple references +pub enum TableSlot { + /// A table cell, with a colspan and a rowspan. + Cell(TableSlotCell), + + /// 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 + /// recent to earliest cell. + /// + /// If there is more than one cell that spans a slot, this is a table model error, but + /// we still keep track of it. See + /// https://html.spec.whatwg.org/multipage/#table-model-error + Spanned(Vec<TableSlotOffset>), + + /// An empty spot in the table. This can happen when there is a gap in columns between + /// cells that are defined and one which should exist because of cell with a rowspan + /// from a previous row. + Empty, +} + +impl std::fmt::Debug for TableSlot { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Cell(_) => f.debug_tuple("Cell").finish(), + Self::Spanned(spanned) => f.debug_tuple("Spanned").field(spanned).finish(), + Self::Empty => write!(f, "Empty"), + } + } +} + +impl TableSlot { + fn new_spanned(offset: TableSlotOffset) -> Self { + Self::Spanned(vec![offset]) + } +} |