typst/src/layout/mod.rs

153 lines
4.8 KiB
Rust

//! Layouting of syntax trees into box layouts.
pub mod elements;
pub mod line;
pub mod primitive;
pub mod stack;
pub mod text;
mod tree;
/// Basic types used across the layouting engine.
pub mod prelude {
pub use super::primitive::*;
pub use super::{layout, BoxLayout, LayoutContext, LayoutSpace, MultiLayout};
pub use Dir::*;
pub use GenAlign::*;
pub use GenAxis::*;
pub use SpecAlign::*;
pub use SpecAxis::*;
}
pub use primitive::*;
pub use tree::layout_tree as layout;
use crate::eval::Scope;
use crate::font::SharedFontLoader;
use crate::geom::{Margins, Size};
use crate::style::{LayoutStyle, PageStyle, TextStyle};
use crate::syntax::SynTree;
use elements::LayoutElements;
use prelude::*;
/// A collection of layouts.
pub type MultiLayout = Vec<BoxLayout>;
/// A finished box with content at fixed positions.
#[derive(Debug, Clone, PartialEq)]
pub struct BoxLayout {
/// The size of the box.
pub size: Size,
/// How to align this box in a parent container.
pub align: LayoutAlign,
/// The elements composing this layout.
pub elements: LayoutElements,
}
/// The context for layouting.
#[derive(Debug, Clone)]
pub struct LayoutContext<'a> {
/// The font loader to query fonts from when typesetting text.
pub loader: &'a SharedFontLoader,
/// The function scope.
pub scope: &'a Scope,
/// The style for pages and text.
pub style: &'a LayoutStyle,
/// The unpadded size of this container (the base 100% for relative sizes).
pub base: Size,
/// The spaces to layout into.
pub spaces: LayoutSpaces,
/// Whether to spill over into copies of the last space or finish layouting
/// when the last space is used up.
pub repeat: bool,
/// The axes along which content is laid out.
pub axes: LayoutAxes,
/// The alignment of the _resulting_ layout. This does not effect the line
/// layouting itself, but rather how the finished layout will be positioned
/// in a parent layout.
pub align: LayoutAlign,
/// Whether this layouting process is the root page-building process.
pub root: bool,
}
/// A collection of layout spaces.
pub type LayoutSpaces = Vec<LayoutSpace>;
/// The space into which content is laid out.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct LayoutSpace {
/// The maximum size of the rectangle to layout into.
pub size: Size,
/// Padding that should be respected on each side.
pub padding: Margins,
/// Whether to expand the size of the resulting layout to the full size of
/// this space or to shrink it to fit the content.
pub expansion: LayoutExpansion,
}
impl LayoutSpace {
/// The offset from the origin to the start of content, i.e.
/// `(padding.left, padding.top)`.
pub fn start(&self) -> Size {
Size::new(self.padding.left, self.padding.top)
}
/// The actually usable area (size minus padding).
pub fn usable(&self) -> Size {
self.size.unpadded(self.padding)
}
/// The inner layout space with size reduced by the padding, zero padding of
/// its own and no layout expansion.
pub fn inner(&self) -> Self {
Self {
size: self.usable(),
padding: Margins::ZERO,
expansion: LayoutExpansion::new(false, false),
}
}
}
/// A sequence of layouting commands.
pub type Commands = Vec<Command>;
/// Commands executable by the layouting engine.
#[derive(Debug, Clone, PartialEq)]
pub enum Command {
/// Layout the given tree in the current context (i.e. not nested). The
/// content of the tree is not laid out into a separate box and then added,
/// but simply laid out flatly in the active layouting process.
///
/// This has the effect that the content fits nicely into the active line
/// layouting, enabling functions to e.g. change the style of some piece of
/// text while keeping it part of the current paragraph.
LayoutSyntaxTree(SynTree),
/// Add a finished layout.
Add(BoxLayout),
/// Add multiple layouts, one after another. This is equivalent to multiple
/// `Add` commands.
AddMultiple(MultiLayout),
/// Add spacing of the given kind along the primary or secondary axis. The
/// kind defines how the spacing interacts with surrounding spacing.
AddSpacing(f64, SpacingKind, GenAxis),
/// Start a new line.
BreakLine,
/// Start a new page, which will be part of the finished layout even if it
/// stays empty (since the page break is a _hard_ space break).
BreakPage,
/// Update the text style.
SetTextStyle(TextStyle),
/// Update the page style.
SetPageStyle(PageStyle),
/// Update the alignment for future boxes added to this layouting process.
SetAlignment(LayoutAlign),
/// Update the layouting axes along which future boxes will be laid
/// out. This ends the current line.
SetAxes(LayoutAxes),
}