summaryrefslogtreecommitdiff
path: root/src/layout/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout/mod.rs')
-rw-r--r--src/layout/mod.rs197
1 files changed, 94 insertions, 103 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 44a2c2fa..d09566e3 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -1,4 +1,4 @@
-//! Layouting of documents.
+//! Layouting.
mod fixed;
mod node;
@@ -20,10 +20,48 @@ pub use spacing::*;
pub use stack::*;
pub use text::*;
-/// Layout a document and return the produced layouts.
-pub fn layout(document: &Document, env: SharedEnv) -> Vec<BoxLayout> {
- let mut ctx = LayoutContext { env };
- document.layout(&mut ctx)
+/// Layout a tree into a collection of frames.
+pub fn layout(tree: &Tree, env: SharedEnv) -> Vec<Frame> {
+ tree.layout(&mut LayoutContext { env })
+}
+
+/// A tree of layout nodes.
+#[derive(Debug, Clone, PartialEq)]
+pub struct Tree {
+ /// Runs of pages with the same properties.
+ pub runs: Vec<NodePages>,
+}
+
+impl Tree {
+ /// Layout the tree into a collection of frames.
+ pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Frame> {
+ self.runs.iter().flat_map(|run| run.layout(ctx)).collect()
+ }
+}
+
+/// A run of pages that all have the same properties.
+#[derive(Debug, Clone, PartialEq)]
+pub struct NodePages {
+ /// The size of each page.
+ pub size: Size,
+ /// The layout node that produces the actual pages (typically a
+ /// [`NodeStack`]).
+ pub child: Node,
+}
+
+impl NodePages {
+ /// Layout the page run.
+ pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Frame> {
+ let areas = Areas::repeat(self.size);
+ let layouted = self.child.layout(ctx, &areas);
+ layouted.frames()
+ }
+}
+
+/// Layout a node.
+pub trait Layout {
+ /// Layout the node into the given areas.
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted;
}
/// The context for layouting.
@@ -33,22 +71,30 @@ pub struct LayoutContext {
pub env: SharedEnv,
}
-/// Layout a node.
-pub trait Layout {
- /// Layout the node into the given areas.
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted;
+/// An area into which content can be laid out.
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct Area {
+ /// The remaining size of this area.
+ pub rem: Size,
+ /// The full size this area once had (used for relative sizing).
+ pub full: Size,
}
-/// A sequence of areas to layout into.
+impl Area {
+ /// Create a new area.
+ pub fn new(size: Size) -> Self {
+ Self { rem: size, full: size }
+ }
+}
+
+/// A collection of areas to layout into.
#[derive(Debug, Clone, PartialEq)]
pub struct Areas {
/// The current area.
pub current: Area,
- /// The backlog of followup areas.
- ///
- /// _Note_: This works stack-like and not queue-like!
+ /// A stack of followup areas (the next area is the last element).
pub backlog: Vec<Size>,
- /// The last area that is repeated when the backlog is empty.
+ /// The final area that is repeated when the backlog is empty.
pub last: Option<Size>,
}
@@ -86,136 +132,81 @@ impl Areas {
}
}
-/// The area into which content can be laid out.
-#[derive(Debug, Copy, Clone, PartialEq)]
-pub struct Area {
- /// The remaining size of this area.
- pub rem: Size,
- /// The full size this area once had (used for relative sizing).
- pub full: Size,
-}
-
-impl Area {
- /// Create a new area.
- pub fn new(size: Size) -> Self {
- Self { rem: size, full: size }
- }
-}
-
-/// How to determine a container's size along an axis.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum Expansion {
- /// Fit the content.
- Fit,
- /// Fill the available space.
- Fill,
-}
-
-impl Expansion {
- /// Returns `Fill` if the condition is true and `Fit` otherwise.
- pub fn fill_if(condition: bool) -> Self {
- if condition { Self::Fill } else { Self::Fit }
- }
-}
-
-/// The result of [layouting](Layout::layout) a node.
+/// The result of layouting a node.
#[derive(Debug, Clone, PartialEq)]
pub enum Layouted {
/// Spacing that should be added to the parent.
Spacing(Length),
/// A layout that should be added to and aligned in the parent.
- Layout(BoxLayout, BoxAlign),
+ Frame(Frame, ChildAlign),
/// Multiple layouts.
- Layouts(Vec<BoxLayout>, BoxAlign),
+ Frames(Vec<Frame>, ChildAlign),
}
impl Layouted {
- /// Return all layouts contained in this variant (zero, one or arbitrarily
+ /// Return all frames contained in this variant (zero, one or arbitrarily
/// many).
- pub fn into_layouts(self) -> Vec<BoxLayout> {
+ pub fn frames(self) -> Vec<Frame> {
match self {
Self::Spacing(_) => vec![],
- Self::Layout(layout, _) => vec![layout],
- Self::Layouts(layouts, _) => layouts,
+ Self::Frame(frame, _) => vec![frame],
+ Self::Frames(frames, _) => frames,
}
}
}
-/// A finished box with content at fixed positions.
+/// Whether to expand or shrink a node along an axis.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Expansion {
+ /// Fit the content.
+ Fit,
+ /// Fill the available space.
+ Fill,
+}
+
+/// A finished layout with elements at fixed positions.
#[derive(Debug, Clone, PartialEq)]
-pub struct BoxLayout {
- /// The size of the box.
+pub struct Frame {
+ /// The size of the frame.
pub size: Size,
/// The elements composing this layout.
- pub elements: Vec<(Point, LayoutElement)>,
+ pub elements: Vec<(Point, Element)>,
}
-impl BoxLayout {
- /// Create a new empty collection.
+impl Frame {
+ /// Create a new, empty frame.
pub fn new(size: Size) -> Self {
Self { size, elements: vec![] }
}
/// Add an element at a position.
- pub fn push(&mut self, pos: Point, element: LayoutElement) {
+ pub fn push(&mut self, pos: Point, element: Element) {
self.elements.push((pos, element));
}
- /// Add all elements of another collection, placing them relative to the
- /// given position.
- pub fn push_layout(&mut self, pos: Point, more: Self) {
- for (subpos, element) in more.elements {
+ /// Add all elements of another frame, placing them relative to the given
+ /// position.
+ pub fn push_frame(&mut self, pos: Point, subframe: Self) {
+ for (subpos, element) in subframe.elements {
self.push(pos + subpos, element);
}
}
}
-/// A layout element, the basic building block layouts are composed of.
+/// The building block frames are composed of.
#[derive(Debug, Clone, PartialEq)]
-pub enum LayoutElement {
+pub enum Element {
/// Shaped text.
Text(Shaped),
/// An image.
- Image(ImageElement),
+ Image(Image),
}
-/// An image.
+/// An image element.
#[derive(Debug, Clone, PartialEq)]
-pub struct ImageElement {
- /// The image.
+pub struct Image {
+ /// The image resource.
pub res: ResourceId,
- /// The document size of the image.
+ /// The size of the image in the document.
pub size: Size,
}
-
-/// The top-level layout node.
-#[derive(Debug, Clone, PartialEq)]
-pub struct Document {
- /// The runs of pages with same properties.
- pub runs: Vec<Pages>,
-}
-
-impl Document {
- /// Layout the document.
- pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
- self.runs.iter().flat_map(|run| run.layout(ctx)).collect()
- }
-}
-
-/// A variable-length run of pages that all have the same properties.
-#[derive(Debug, Clone, PartialEq)]
-pub struct Pages {
- /// The size of each page.
- pub size: Size,
- /// The layout node that produces the actual pages (typically a [`Stack`]).
- pub child: LayoutNode,
-}
-
-impl Pages {
- /// Layout the page run.
- pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
- let areas = Areas::repeat(self.size);
- let layouted = self.child.layout(ctx, &areas);
- layouted.into_layouts()
- }
-}