mod layouter;
mod lines;
mod repeated;
mod rowspans;
pub use self::layouter::GridLayouter;
use typst_library::diag::SourceResult;
use typst_library::engine::Engine;
use typst_library::foundations::{Content, NativeElement, Packed, StyleChain};
use typst_library::introspection::{Location, Locator, SplitLocator, Tag, TagFlags};
use typst_library::layout::grid::resolve::Cell;
use typst_library::layout::{
Fragment, FrameItem, FrameParent, GridCell, GridElem, Inherit, Point, Regions,
};
use typst_library::model::{TableCell, TableElem};
use self::layouter::RowPiece;
use self::lines::{
LineSegment, generate_line_segments, hline_stroke_at_column, vline_stroke_at_row,
};
use self::rowspans::{Rowspan, UnbreakableRowGroup};
pub fn layout_cell(
cell: &Cell,
engine: &mut Engine,
locator: Locator,
styles: StyleChain,
regions: Regions,
is_repeated: bool,
) -> SourceResult<Fragment> {
let mut locator = locator.split();
let mut tags = None;
if let Some(table_cell) = cell.body.to_packed::<TableCell>() {
let mut table_cell = table_cell.clone();
table_cell.is_repeated.set(is_repeated);
tags = Some(generate_tags(table_cell, &mut locator, engine));
} else if let Some(grid_cell) = cell.body.to_packed::<GridCell>() {
let mut grid_cell = grid_cell.clone();
grid_cell.is_repeated.set(is_repeated);
tags = Some(generate_tags(grid_cell, &mut locator, engine));
}
let locator = locator.next(&cell.body.span());
let fragment = crate::layout_fragment(engine, &cell.body, locator, styles, regions)?;
let mut frames = fragment.into_frames();
if let Some((elem, loc, key)) = tags
&& let Some((first, remainder)) = frames.split_first_mut()
{
let flags = TagFlags { introspectable: true, tagged: true };
if remainder.is_empty() {
first.prepend(Point::zero(), FrameItem::Tag(Tag::Start(elem, flags)));
first.push(Point::zero(), FrameItem::Tag(Tag::End(loc, key, flags)));
} else {
for frame in frames.iter_mut() {
frame.set_parent(FrameParent::new(loc, Inherit::Yes));
}
frames.first_mut().unwrap().prepend_multiple([
(Point::zero(), FrameItem::Tag(Tag::Start(elem, flags))),
(Point::zero(), FrameItem::Tag(Tag::End(loc, key, flags))),
]);
}
}
Ok(Fragment::frames(frames))
}
fn generate_tags<T: NativeElement>(
mut cell: Packed<T>,
locator: &mut SplitLocator,
engine: &mut Engine,
) -> (Content, Location, u128) {
let key = typst_utils::hash128(&cell);
let loc = locator.next_location(engine.introspector, key);
cell.set_location(loc);
(cell.pack(), loc, key)
}
#[typst_macros::time(span = elem.span())]
pub fn layout_grid(
elem: &Packed<GridElem>,
engine: &mut Engine,
locator: Locator,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let grid = elem.grid.as_ref().unwrap();
GridLayouter::new(grid, regions, locator, styles, elem.span()).layout(engine)
}
#[typst_macros::time(span = elem.span())]
pub fn layout_table(
elem: &Packed<TableElem>,
engine: &mut Engine,
locator: Locator,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let grid = elem.grid.as_ref().unwrap();
GridLayouter::new(grid, regions, locator, styles, elem.span()).layout(engine)
}