summaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/background.rs10
-rw-r--r--src/layout/fixed.rs4
-rw-r--r--src/layout/mod.rs121
-rw-r--r--src/layout/node.rs108
-rw-r--r--src/layout/pad.rs12
-rw-r--r--src/layout/par.rs127
-rw-r--r--src/layout/spacing.rs35
-rw-r--r--src/layout/stack.rs76
-rw-r--r--src/layout/text.rs36
9 files changed, 195 insertions, 334 deletions
diff --git a/src/layout/background.rs b/src/layout/background.rs
index 17280a86..d3408182 100644
--- a/src/layout/background.rs
+++ b/src/layout/background.rs
@@ -8,7 +8,7 @@ pub struct BackgroundNode {
/// The background fill.
pub fill: Fill,
/// The child node to be filled.
- pub child: Node,
+ pub child: AnyNode,
}
/// The kind of shape to use as a background.
@@ -19,10 +19,10 @@ pub enum BackgroundShape {
}
impl Layout for BackgroundNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
- let mut fragment = self.child.layout(ctx, areas);
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
+ let mut frames = self.child.layout(ctx, areas);
- for frame in fragment.frames_mut() {
+ for frame in &mut frames {
let (point, shape) = match self.shape {
BackgroundShape::Rect => (Point::ZERO, Shape::Rect(frame.size)),
BackgroundShape::Ellipse => {
@@ -34,7 +34,7 @@ impl Layout for BackgroundNode {
frame.elements.insert(0, (point, element));
}
- fragment
+ frames
}
}
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index 22c45ef1..04ea5a3a 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -12,11 +12,11 @@ pub struct FixedNode {
/// The resulting frame will satisfy `width = aspect * height`.
pub aspect: Option<f64>,
/// The child node whose size to fix.
- pub child: Node,
+ pub child: AnyNode,
}
impl Layout for FixedNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let Areas { current, full, .. } = areas;
let full = Size::new(
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 360c9d84..6f28fcb9 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -3,24 +3,21 @@
mod background;
mod fixed;
mod frame;
-mod node;
mod pad;
mod par;
mod shaping;
-mod spacing;
mod stack;
-mod text;
pub use background::*;
pub use fixed::*;
pub use frame::*;
-pub use node::*;
pub use pad::*;
pub use par::*;
pub use shaping::*;
-pub use spacing::*;
pub use stack::*;
-pub use text::*;
+
+use std::any::Any;
+use std::fmt::{self, Debug, Formatter};
use crate::env::Env;
use crate::geom::*;
@@ -51,25 +48,88 @@ pub struct PageRun {
pub size: Size,
/// The layout node that produces the actual pages (typically a
/// [`StackNode`]).
- pub child: Node,
+ pub child: AnyNode,
}
impl PageRun {
/// Layout the page run.
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Frame> {
let areas = Areas::repeat(self.size, Spec::uniform(Expand::Fill));
- self.child.layout(ctx, &areas).into_frames()
+ self.child.layout(ctx, &areas)
+ }
+}
+
+/// A wrapper around a dynamic layouting node.
+pub struct AnyNode(Box<dyn Bounds>);
+
+impl AnyNode {
+ /// Create a new instance from any node that satisifies the required bounds.
+ pub fn new<T>(any: T) -> Self
+ where
+ T: Layout + Debug + Clone + PartialEq + 'static,
+ {
+ Self(Box::new(any))
+ }
+}
+
+impl Layout for AnyNode {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
+ self.0.layout(ctx, areas)
+ }
+}
+
+impl Clone for AnyNode {
+ fn clone(&self) -> Self {
+ Self(self.0.dyn_clone())
+ }
+}
+
+impl PartialEq for AnyNode {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.dyn_eq(other.0.as_ref())
+ }
+}
+
+impl Debug for AnyNode {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+trait Bounds: Layout + Debug + 'static {
+ fn as_any(&self) -> &dyn Any;
+ fn dyn_eq(&self, other: &dyn Bounds) -> bool;
+ fn dyn_clone(&self) -> Box<dyn Bounds>;
+}
+
+impl<T> Bounds for T
+where
+ T: Layout + Debug + PartialEq + Clone + 'static,
+{
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ fn dyn_eq(&self, other: &dyn Bounds) -> bool {
+ if let Some(other) = other.as_any().downcast_ref::<Self>() {
+ self == other
+ } else {
+ false
+ }
+ }
+
+ fn dyn_clone(&self) -> Box<dyn Bounds> {
+ Box::new(self.clone())
}
}
/// Layout a node.
pub trait Layout {
/// Layout the node into the given areas.
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment;
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame>;
}
/// The context for layouting.
-#[derive(Debug)]
pub struct LayoutContext<'a> {
/// The environment from which fonts are gathered.
pub env: &'a mut Env,
@@ -183,44 +243,3 @@ impl Expand {
}
}
}
-
-/// The result of layouting a node.
-#[derive(Debug, Clone, PartialEq)]
-pub enum Fragment {
- /// Spacing that should be added to the parent.
- Spacing(Length),
- /// A layout that should be added to and aligned in the parent.
- Frame(Frame, LayoutAligns),
- /// Multiple layouts.
- Frames(Vec<Frame>, LayoutAligns),
-}
-
-impl Fragment {
- /// Return a reference to all frames contained in this variant (zero, one or
- /// arbitrarily many).
- pub fn frames(&self) -> &[Frame] {
- match self {
- Self::Spacing(_) => &[],
- Self::Frame(frame, _) => std::slice::from_ref(frame),
- Self::Frames(frames, _) => frames,
- }
- }
-
- /// Return a mutable reference to all frames contained in this variant.
- pub fn frames_mut(&mut self) -> &mut [Frame] {
- match self {
- Self::Spacing(_) => &mut [],
- Self::Frame(frame, _) => std::slice::from_mut(frame),
- Self::Frames(frames, _) => frames,
- }
- }
-
- /// Return all frames contained in this varian.
- pub fn into_frames(self) -> Vec<Frame> {
- match self {
- Self::Spacing(_) => vec![],
- Self::Frame(frame, _) => vec![frame],
- Self::Frames(frames, _) => frames,
- }
- }
-}
diff --git a/src/layout/node.rs b/src/layout/node.rs
deleted file mode 100644
index 443a96ae..00000000
--- a/src/layout/node.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use std::any::Any;
-use std::fmt::{self, Debug, Formatter};
-
-use super::*;
-
-/// A self-contained layout node.
-#[derive(Clone, PartialEq)]
-pub enum Node {
- /// A text node.
- Text(TextNode),
- /// A spacing node.
- Spacing(SpacingNode),
- /// A dynamic node that can implement custom layouting behaviour.
- Any(AnyNode),
-}
-
-impl Layout for Node {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
- match self {
- Self::Spacing(spacing) => spacing.layout(ctx, areas),
- Self::Text(text) => text.layout(ctx, areas),
- Self::Any(any) => any.layout(ctx, areas),
- }
- }
-}
-
-impl Debug for Node {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- match self {
- Self::Spacing(spacing) => spacing.fmt(f),
- Self::Text(text) => text.fmt(f),
- Self::Any(any) => any.fmt(f),
- }
- }
-}
-
-/// A wrapper around a dynamic layouting node.
-pub struct AnyNode(Box<dyn Bounds>);
-
-impl AnyNode {
- /// Create a new instance from any node that satisifies the required bounds.
- pub fn new<T>(any: T) -> Self
- where
- T: Layout + Debug + Clone + PartialEq + 'static,
- {
- Self(Box::new(any))
- }
-}
-
-impl Layout for AnyNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
- self.0.layout(ctx, areas)
- }
-}
-
-impl Clone for AnyNode {
- fn clone(&self) -> Self {
- Self(self.0.dyn_clone())
- }
-}
-
-impl PartialEq for AnyNode {
- fn eq(&self, other: &Self) -> bool {
- self.0.dyn_eq(other.0.as_ref())
- }
-}
-
-impl Debug for AnyNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.0.fmt(f)
- }
-}
-
-impl<T> From<T> for Node
-where
- T: Into<AnyNode>,
-{
- fn from(t: T) -> Self {
- Self::Any(t.into())
- }
-}
-
-trait Bounds: Layout + Debug + 'static {
- fn as_any(&self) -> &dyn Any;
- fn dyn_eq(&self, other: &dyn Bounds) -> bool;
- fn dyn_clone(&self) -> Box<dyn Bounds>;
-}
-
-impl<T> Bounds for T
-where
- T: Layout + Debug + PartialEq + Clone + 'static,
-{
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn dyn_eq(&self, other: &dyn Bounds) -> bool {
- if let Some(other) = other.as_any().downcast_ref::<Self>() {
- self == other
- } else {
- false
- }
- }
-
- fn dyn_clone(&self) -> Box<dyn Bounds> {
- Box::new(self.clone())
- }
-}
diff --git a/src/layout/pad.rs b/src/layout/pad.rs
index fb038996..2c8712af 100644
--- a/src/layout/pad.rs
+++ b/src/layout/pad.rs
@@ -6,19 +6,17 @@ pub struct PadNode {
/// The amount of padding.
pub padding: Sides<Linear>,
/// The child node whose sides to pad.
- pub child: Node,
+ pub child: AnyNode,
}
impl Layout for PadNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let areas = shrink(areas, self.padding);
-
- let mut fragment = self.child.layout(ctx, &areas);
- for frame in fragment.frames_mut() {
+ let mut frames = self.child.layout(ctx, &areas);
+ for frame in &mut frames {
pad(frame, self.padding);
}
-
- fragment
+ frames
}
}
diff --git a/src/layout/par.rs b/src/layout/par.rs
index 0364a03a..02e27cbd 100644
--- a/src/layout/par.rs
+++ b/src/layout/par.rs
@@ -1,38 +1,63 @@
+use std::fmt::{self, Debug, Formatter};
+
use super::*;
+use crate::exec::FontProps;
/// A node that arranges its children into a paragraph.
#[derive(Debug, Clone, PartialEq)]
pub struct ParNode {
- /// The `main` and `cross` directions of this paragraph.
- ///
- /// The children are placed in lines along the `cross` direction. The lines
- /// are stacked along the `main` direction.
- pub dirs: LayoutDirs,
- /// How to align this paragraph in its parent.
- pub aligns: LayoutAligns,
- /// The spacing to insert after each line.
+ /// The inline direction of this paragraph.
+ pub dir: Dir,
+ /// The spacing to insert between each line.
pub line_spacing: Length,
/// The nodes to be arranged in a paragraph.
- pub children: Vec<Node>,
+ pub children: Vec<ParChild>,
+}
+
+/// A child of a paragraph node.
+#[derive(Debug, Clone, PartialEq)]
+pub enum ParChild {
+ /// Spacing between other nodes.
+ Spacing(Length),
+ /// A run of text and how to align it in its line.
+ Text(TextNode, Align),
+ /// Any child node and how to align it in its line.
+ Any(AnyNode, Align),
+}
+
+/// A consecutive, styled run of text.
+#[derive(Clone, PartialEq)]
+pub struct TextNode {
+ /// The text.
+ pub text: String,
+ /// Properties used for font selection and layout.
+ pub props: FontProps,
+}
+
+impl Debug for TextNode {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "Text({})", self.text)
+ }
}
impl Layout for ParNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
- let mut layouter = ParLayouter::new(self.dirs, self.line_spacing, areas.clone());
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
+ let mut layouter = ParLayouter::new(self.dir, self.line_spacing, areas.clone());
for child in &self.children {
- match child.layout(ctx, &layouter.areas) {
- Fragment::Spacing(spacing) => layouter.push_spacing(spacing),
- Fragment::Frame(frame, aligns) => {
- layouter.push_frame(frame, aligns.cross)
+ match *child {
+ ParChild::Spacing(amount) => layouter.push_spacing(amount),
+ ParChild::Text(ref node, align) => {
+ let frame = shape(&node.text, &mut ctx.env.fonts, &node.props);
+ layouter.push_frame(frame, align);
}
- Fragment::Frames(frames, aligns) => {
- for frame in frames {
- layouter.push_frame(frame, aligns.cross);
+ ParChild::Any(ref node, align) => {
+ for frame in node.layout(ctx, &layouter.areas) {
+ layouter.push_frame(frame, align);
}
}
}
}
- Fragment::Frames(layouter.finish(), self.aligns)
+ layouter.finish()
}
}
@@ -43,30 +68,30 @@ impl From<ParNode> for AnyNode {
}
struct ParLayouter {
+ dirs: Gen<Dir>,
main: SpecAxis,
cross: SpecAxis,
- dirs: LayoutDirs,
line_spacing: Length,
areas: Areas,
finished: Vec<Frame>,
- lines: Vec<(Length, Frame, Align)>,
- lines_size: Gen<Length>,
+ stack: Vec<(Length, Frame, Align)>,
+ stack_size: Gen<Length>,
line: Vec<(Length, Frame, Align)>,
line_size: Gen<Length>,
line_ruler: Align,
}
impl ParLayouter {
- fn new(dirs: LayoutDirs, line_spacing: Length, areas: Areas) -> Self {
+ fn new(dir: Dir, line_spacing: Length, areas: Areas) -> Self {
Self {
- main: dirs.main.axis(),
- cross: dirs.cross.axis(),
- dirs,
+ dirs: Gen::new(Dir::TTB, dir),
+ main: SpecAxis::Vertical,
+ cross: SpecAxis::Horizontal,
line_spacing,
areas,
finished: vec![],
- lines: vec![],
- lines_size: Gen::ZERO,
+ stack: vec![],
+ stack_size: Gen::ZERO,
line: vec![],
line_size: Gen::ZERO,
line_ruler: Align::Start,
@@ -122,12 +147,10 @@ impl ParLayouter {
}
}
- let size = frame.size.switch(self.dirs);
-
// A line can contain frames with different alignments. They exact
// positions are calculated later depending on the alignments.
+ let size = frame.size.switch(self.main);
self.line.push((self.line_size.cross, frame, align));
-
self.line_size.cross += size.cross;
self.line_size.main = self.line_size.main.max(size.main);
self.line_ruler = align;
@@ -135,15 +158,15 @@ impl ParLayouter {
fn finish_line(&mut self) {
let full_size = {
- let expand = self.areas.expand.switch(self.dirs);
- let full = self.areas.full.switch(self.dirs);
+ let expand = self.areas.expand.get(self.cross);
+ let full = self.areas.full.get(self.cross);
Gen::new(
self.line_size.main,
- expand.cross.resolve(self.line_size.cross, full.cross),
+ expand.resolve(self.line_size.cross, full),
)
};
- let mut output = Frame::new(full_size.switch(self.dirs).to_size());
+ let mut output = Frame::new(full_size.switch(self.main).to_size());
for (before, frame, align) in std::mem::take(&mut self.line) {
let child_cross_size = frame.size.get(self.cross);
@@ -158,49 +181,47 @@ impl ParLayouter {
full_size.cross - before_with_self .. after
});
- let pos = Gen::new(Length::ZERO, cross).switch(self.dirs).to_point();
+ let pos = Gen::new(Length::ZERO, cross).switch(self.main).to_point();
output.push_frame(pos, frame);
}
// Add line spacing, but only between lines.
- if !self.lines.is_empty() {
- self.lines_size.main += self.line_spacing;
+ if !self.stack.is_empty() {
+ self.stack_size.main += self.line_spacing;
*self.areas.current.get_mut(self.main) -= self.line_spacing;
}
- // Update metrics of the whole paragraph.
- self.lines.push((self.lines_size.main, output, self.line_ruler));
- self.lines_size.main += full_size.main;
- self.lines_size.cross = self.lines_size.cross.max(full_size.cross);
+ // Update metrics of paragraph and reset for line.
+ self.stack.push((self.stack_size.main, output, self.line_ruler));
+ self.stack_size.main += full_size.main;
+ self.stack_size.cross = self.stack_size.cross.max(full_size.cross);
*self.areas.current.get_mut(self.main) -= full_size.main;
-
- // Reset metrics for the single line.
self.line_size = Gen::ZERO;
self.line_ruler = Align::Start;
}
fn finish_area(&mut self) {
- let size = self.lines_size;
- let mut output = Frame::new(size.switch(self.dirs).to_size());
+ let full_size = self.stack_size;
+ let mut output = Frame::new(full_size.switch(self.main).to_size());
- for (before, line, cross_align) in std::mem::take(&mut self.lines) {
- let child_size = line.size.switch(self.dirs);
+ for (before, line, cross_align) in std::mem::take(&mut self.stack) {
+ let child_size = line.size.switch(self.main);
// Position along the main axis.
let main = if self.dirs.main.is_positive() {
before
} else {
- size.main - (before + child_size.main)
+ full_size.main - (before + child_size.main)
};
// Align along the cross axis.
let cross = cross_align.resolve(if self.dirs.cross.is_positive() {
- Length::ZERO .. size.cross - child_size.cross
+ Length::ZERO .. full_size.cross - child_size.cross
} else {
- size.cross - child_size.cross .. Length::ZERO
+ full_size.cross - child_size.cross .. Length::ZERO
});
- let pos = Gen::new(main, cross).switch(self.dirs).to_point();
+ let pos = Gen::new(main, cross).switch(self.main).to_point();
output.push_frame(pos, line);
}
@@ -208,7 +229,7 @@ impl ParLayouter {
self.areas.next();
// Reset metrics for the whole paragraph.
- self.lines_size = Gen::ZERO;
+ self.stack_size = Gen::ZERO;
}
fn finish(mut self) -> Vec<Frame> {
diff --git a/src/layout/spacing.rs b/src/layout/spacing.rs
deleted file mode 100644
index 361b03ee..00000000
--- a/src/layout/spacing.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::fmt::{self, Debug, Formatter};
-
-use super::*;
-
-/// A node that adds spacing to its parent.
-#[derive(Copy, Clone, PartialEq)]
-pub struct SpacingNode {
- /// The amount of spacing to insert.
- pub amount: Length,
- /// Defines how spacing interacts with surrounding spacing.
- ///
- /// Hard spacing (`softness = 0`) assures that a fixed amount of spacing
- /// will always be inserted. Soft spacing (`softness >= 1`) will be consumed
- /// by other spacing with lower softness and can be used to insert
- /// overridable spacing, e.g. between words or paragraphs.
- pub softness: u8,
-}
-
-impl Layout for SpacingNode {
- fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Fragment {
- Fragment::Spacing(self.amount)
- }
-}
-
-impl Debug for SpacingNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Spacing({}, {})", self.amount, self.softness)
- }
-}
-
-impl From<SpacingNode> for Node {
- fn from(spacing: SpacingNode) -> Self {
- Self::Spacing(spacing)
- }
-}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index 6a87290e..79fde72d 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -7,28 +7,34 @@ pub struct StackNode {
///
/// The children are stacked along the `main` direction. The `cross`
/// direction is required for aligning the children.
- pub dirs: LayoutDirs,
- /// How to align this stack in its parent.
- pub aligns: LayoutAligns,
+ pub dirs: Gen<Dir>,
/// The nodes to be stacked.
- pub children: Vec<Node>,
+ pub children: Vec<StackChild>,
+}
+
+/// A child of a stack node.
+#[derive(Debug, Clone, PartialEq)]
+pub enum StackChild {
+ /// Spacing between other nodes.
+ Spacing(Length),
+ /// Any child node and how to align it in the stack.
+ Any(AnyNode, Gen<Align>),
}
impl Layout for StackNode {
- fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Fragment {
+ fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let mut layouter = StackLayouter::new(self.dirs, areas.clone());
for child in &self.children {
- match child.layout(ctx, &layouter.areas) {
- Fragment::Spacing(spacing) => layouter.push_spacing(spacing),
- Fragment::Frame(frame, aligns) => layouter.push_frame(frame, aligns),
- Fragment::Frames(frames, aligns) => {
- for frame in frames {
+ match *child {
+ StackChild::Spacing(amount) => layouter.push_spacing(amount),
+ StackChild::Any(ref node, aligns) => {
+ for frame in node.layout(ctx, &layouter.areas) {
layouter.push_frame(frame, aligns);
}
}
}
}
- Fragment::Frames(layouter.finish(), self.aligns)
+ layouter.finish()
}
}
@@ -39,24 +45,24 @@ impl From<StackNode> for AnyNode {
}
struct StackLayouter {
+ dirs: Gen<Dir>,
main: SpecAxis,
- dirs: LayoutDirs,
areas: Areas,
finished: Vec<Frame>,
- frames: Vec<(Length, Frame, LayoutAligns)>,
- used: Gen<Length>,
+ frames: Vec<(Length, Frame, Gen<Align>)>,
+ size: Gen<Length>,
ruler: Align,
}
impl StackLayouter {
- fn new(dirs: LayoutDirs, areas: Areas) -> Self {
+ fn new(dirs: Gen<Dir>, areas: Areas) -> Self {
Self {
- main: dirs.main.axis(),
dirs,
+ main: dirs.main.axis(),
areas,
finished: vec![],
frames: vec![],
- used: Gen::ZERO,
+ size: Gen::ZERO,
ruler: Align::Start,
}
}
@@ -65,10 +71,10 @@ impl StackLayouter {
let main_rest = self.areas.current.get_mut(self.main);
let capped = amount.min(*main_rest);
*main_rest -= capped;
- self.used.main += capped;
+ self.size.main += capped;
}
- fn push_frame(&mut self, frame: Frame, aligns: LayoutAligns) {
+ fn push_frame(&mut self, frame: Frame, aligns: Gen<Align>) {
if self.ruler > aligns.main {
self.finish_area();
}
@@ -82,21 +88,18 @@ impl StackLayouter {
}
}
- let size = frame.size.switch(self.dirs);
- self.frames.push((self.used.main, frame, aligns));
-
- *self.areas.current.get_mut(self.main) -= size.main;
- self.used.main += size.main;
- self.used.cross = self.used.cross.max(size.cross);
+ let size = frame.size.switch(self.main);
+ self.frames.push((self.size.main, frame, aligns));
self.ruler = aligns.main;
+ self.size.main += size.main;
+ self.size.cross = self.size.cross.max(size.cross);
+ *self.areas.current.get_mut(self.main) -= size.main;
}
fn finish_area(&mut self) {
let full_size = {
- let expand = self.areas.expand;
- let full = self.areas.full;
- let current = self.areas.current;
- let used = self.used.switch(self.dirs).to_size();
+ let Areas { current, full, expand, .. } = self.areas;
+ let used = self.size.switch(self.main).to_size();
let mut size = Size::new(
expand.horizontal.resolve(used.width, full.width),
@@ -113,21 +116,21 @@ impl StackLayouter {
size = Size::new(width, width / aspect);
}
- size.switch(self.dirs)
+ size.switch(self.main)
};
- let mut output = Frame::new(full_size.switch(self.dirs).to_size());
+ let mut output = Frame::new(full_size.switch(self.main).to_size());
for (before, frame, aligns) in std::mem::take(&mut self.frames) {
- let child_size = frame.size.switch(self.dirs);
+ let child_size = frame.size.switch(self.main);
// Align along the main axis.
let main = aligns.main.resolve(if self.dirs.main.is_positive() {
- let after_with_self = self.used.main - before;
+ let after_with_self = self.size.main - before;
before .. full_size.main - after_with_self
} else {
let before_with_self = before + child_size.main;
- let after = self.used.main - (before + child_size.main);
+ let after = self.size.main - (before + child_size.main);
full_size.main - before_with_self .. after
});
@@ -138,15 +141,14 @@ impl StackLayouter {
full_size.cross - child_size.cross .. Length::ZERO
});
- let pos = Gen::new(main, cross).switch(self.dirs).to_point();
+ let pos = Gen::new(main, cross).switch(self.main).to_point();
output.push_frame(pos, frame);
}
self.finished.push(output);
-
self.areas.next();
- self.used = Gen::ZERO;
self.ruler = Align::Start;
+ self.size = Gen::ZERO;
}
fn finish(mut self) -> Vec<Frame> {
diff --git a/src/layout/text.rs b/src/layout/text.rs
deleted file mode 100644
index 39866907..00000000
--- a/src/layout/text.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::fmt::{self, Debug, Formatter};
-
-use super::*;
-use crate::exec::FontProps;
-
-/// A consecutive, styled run of text.
-#[derive(Clone, PartialEq)]
-pub struct TextNode {
- /// The text direction.
- pub dir: Dir,
- /// How to align this text node in its parent.
- pub aligns: LayoutAligns,
- /// The text.
- pub text: String,
- /// Properties used for font selection and layout.
- pub props: FontProps,
-}
-
-impl Layout for TextNode {
- fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Fragment {
- let frame = shape(&self.text, &mut ctx.env.fonts, &self.props);
- Fragment::Frame(frame, self.aligns)
- }
-}
-
-impl Debug for TextNode {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Text({})", self.text)
- }
-}
-
-impl From<TextNode> for Node {
- fn from(text: TextNode) -> Self {
- Self::Text(text)
- }
-}