summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-12-30 11:37:11 +0100
committerLaurenz <laurmaedje@gmail.com>2021-12-30 12:00:12 +0100
commitf5dcb84e36a38182218c7f907b861b12d2bd2c1c (patch)
tree1fce04fb53d2ad5b61f5f3151e43d80e2684e579 /src/library
parentfef55025177ea4f248e61b68fab365bfbc0e47fb (diff)
Make clippy a bit happier
Diffstat (limited to 'src/library')
-rw-r--r--src/library/align.rs6
-rw-r--r--src/library/columns.rs9
-rw-r--r--src/library/flow.rs58
-rw-r--r--src/library/grid.rs24
-rw-r--r--src/library/heading.rs9
-rw-r--r--src/library/list.rs7
-rw-r--r--src/library/mod.rs6
-rw-r--r--src/library/pad.rs4
-rw-r--r--src/library/page.rs19
-rw-r--r--src/library/par.rs17
-rw-r--r--src/library/placed.rs4
-rw-r--r--src/library/shape.rs4
-rw-r--r--src/library/sized.rs10
-rw-r--r--src/library/stack.rs111
-rw-r--r--src/library/text.rs11
-rw-r--r--src/library/transform.rs6
16 files changed, 152 insertions, 153 deletions
diff --git a/src/library/align.rs b/src/library/align.rs
index 16c44905..5f21fa37 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -6,16 +6,14 @@ use super::ParNode;
/// `align`: Configure the alignment along the layouting axes.
pub fn align(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let aligns: Spec<_> = args.find().unwrap_or_default();
- let body: Node = args.expect("body")?;
+ let body: PackedNode = args.expect("body")?;
let mut styles = Styles::new();
if let Some(align) = aligns.x {
styles.set(ParNode::ALIGN, align);
}
- Ok(Value::block(
- body.into_block().styled(styles).aligned(aligns),
- ))
+ Ok(Value::block(body.styled(styles).aligned(aligns)))
}
dynamic! {
diff --git a/src/library/columns.rs b/src/library/columns.rs
index df55fb52..f5d06e56 100644
--- a/src/library/columns.rs
+++ b/src/library/columns.rs
@@ -5,13 +5,10 @@ use super::ParNode;
/// `columns`: Set content into multiple columns.
pub fn columns(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
- let columns = args.expect("column count")?;
- let gutter = args.named("gutter")?.unwrap_or(Relative::new(0.04).into());
- let body: Node = args.expect("body")?;
Ok(Value::block(ColumnsNode {
- columns,
- gutter,
- child: body.into_block(),
+ columns: args.expect("column count")?,
+ gutter: args.named("gutter")?.unwrap_or(Relative::new(0.04).into()),
+ child: args.expect("body")?,
}))
}
diff --git a/src/library/flow.rs b/src/library/flow.rs
index 810e566a..10d57022 100644
--- a/src/library/flow.rs
+++ b/src/library/flow.rs
@@ -18,7 +18,7 @@ impl Layout for FlowNode {
ctx: &mut LayoutContext,
regions: &Regions,
) -> Vec<Constrained<Rc<Frame>>> {
- FlowLayouter::new(self, regions).layout(ctx)
+ FlowLayouter::new(self, regions.clone()).layout(ctx)
}
}
@@ -32,12 +32,12 @@ impl Debug for FlowNode {
/// A child of a flow node.
#[derive(Hash)]
pub enum FlowChild {
- /// A paragraph/block break.
- Break(Styles),
/// Vertical spacing between other children.
Spacing(SpacingNode),
/// An arbitrary node.
Node(PackedNode),
+ /// A paragraph/block break.
+ Break(Styles),
/// Skip the rest of the region and move to the next.
Skip,
}
@@ -46,9 +46,9 @@ impl FlowChild {
/// A reference to the child's styles.
pub fn styles(&self) -> Option<&Styles> {
match self {
- Self::Break(styles) => Some(styles),
Self::Spacing(node) => Some(&node.styles),
Self::Node(node) => Some(&node.styles),
+ Self::Break(styles) => Some(styles),
Self::Skip => None,
}
}
@@ -56,9 +56,9 @@ impl FlowChild {
/// A mutable reference to the child's styles.
pub fn styles_mut(&mut self) -> Option<&mut Styles> {
match self {
- Self::Break(styles) => Some(styles),
Self::Spacing(node) => Some(&mut node.styles),
Self::Node(node) => Some(&mut node.styles),
+ Self::Break(styles) => Some(styles),
Self::Skip => None,
}
}
@@ -67,14 +67,14 @@ impl FlowChild {
impl Debug for FlowChild {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
+ Self::Spacing(node) => node.fmt(f),
+ Self::Node(node) => node.fmt(f),
Self::Break(styles) => {
if f.alternate() {
styles.fmt(f)?;
}
write!(f, "Break")
}
- Self::Spacing(node) => node.fmt(f),
- Self::Node(node) => node.fmt(f),
Self::Skip => f.pad("Skip"),
}
}
@@ -84,10 +84,10 @@ impl Debug for FlowChild {
struct FlowLayouter<'a> {
/// The flow node to layout.
children: &'a [FlowChild],
- /// Whether the flow should expand to fill the region.
- expand: Spec<bool>,
/// The regions to layout children into.
regions: Regions,
+ /// Whether the flow should expand to fill the region.
+ expand: Spec<bool>,
/// The full size of `regions.current` that was available before we started
/// subtracting.
full: Size,
@@ -115,19 +115,18 @@ enum FlowItem {
impl<'a> FlowLayouter<'a> {
/// Create a new flow layouter.
- fn new(flow: &'a FlowNode, regions: &Regions) -> Self {
+ fn new(flow: &'a FlowNode, mut regions: Regions) -> Self {
let expand = regions.expand;
let full = regions.current;
// Disable vertical expansion for children.
- let mut regions = regions.clone();
regions.expand.y = false;
Self {
children: &flow.0,
+ regions,
expand,
full,
- regions,
used: Size::zero(),
fr: Fractional::zero(),
items: vec![],
@@ -139,6 +138,16 @@ impl<'a> FlowLayouter<'a> {
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
for child in self.children {
match child {
+ FlowChild::Spacing(node) => {
+ self.layout_spacing(node.kind);
+ }
+ FlowChild::Node(node) => {
+ if self.regions.is_full() {
+ self.finish_region();
+ }
+
+ self.layout_node(ctx, node);
+ }
FlowChild::Break(styles) => {
let chain = styles.chain(&ctx.styles);
let em = chain.get(TextNode::SIZE).abs;
@@ -148,20 +157,6 @@ impl<'a> FlowLayouter<'a> {
FlowChild::Skip => {
self.finish_region();
}
- FlowChild::Spacing(node) => match node.kind {
- SpacingKind::Linear(v) => self.layout_absolute(v),
- SpacingKind::Fractional(v) => {
- self.items.push(FlowItem::Fractional(v));
- self.fr += v;
- }
- },
- FlowChild::Node(node) => {
- if self.regions.is_full() {
- self.finish_region();
- }
-
- self.layout_node(ctx, node);
- }
}
}
@@ -169,6 +164,17 @@ impl<'a> FlowLayouter<'a> {
self.finished
}
+ /// Layout spacing.
+ fn layout_spacing(&mut self, spacing: SpacingKind) {
+ match spacing {
+ SpacingKind::Linear(v) => self.layout_absolute(v),
+ SpacingKind::Fractional(v) => {
+ self.items.push(FlowItem::Fractional(v));
+ self.fr += v;
+ }
+ }
+ }
+
/// Layout absolute spacing.
fn layout_absolute(&mut self, amount: Linear) {
// Resolve the linear, limiting it to the remaining available space.
diff --git a/src/library/grid.rs b/src/library/grid.rs
index 3292cfe0..cc636afc 100644
--- a/src/library/grid.rs
+++ b/src/library/grid.rs
@@ -15,7 +15,7 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
column_gutter.unwrap_or_else(|| base_gutter.clone()),
row_gutter.unwrap_or(base_gutter),
),
- children: args.all().map(Node::into_block).collect(),
+ children: args.all().collect(),
}))
}
@@ -87,8 +87,6 @@ castable! {
struct GridLayouter<'a> {
/// The children of the grid.
children: &'a [PackedNode],
- /// Whether the grid should expand to fill the region.
- expand: Spec<bool>,
/// The column tracks including gutter tracks.
cols: Vec<TrackSizing>,
/// The row tracks including gutter tracks.
@@ -97,6 +95,10 @@ struct GridLayouter<'a> {
regions: Regions,
/// Resolved column sizes.
rcols: Vec<Length>,
+ /// Rows in the current region.
+ lrows: Vec<Row>,
+ /// Whether the grid should expand to fill the region.
+ expand: Spec<bool>,
/// The full height of the current region.
full: Length,
/// The used-up size of the current region. The horizontal size is
@@ -104,8 +106,6 @@ struct GridLayouter<'a> {
used: Size,
/// The sum of fractional ratios in the current region.
fr: Fractional,
- /// Rows in the current region.
- lrows: Vec<Row>,
/// Constraints for the active region.
cts: Constraints,
/// Frames for finished regions.
@@ -161,22 +161,26 @@ impl<'a> GridLayouter<'a> {
cols.pop();
rows.pop();
+ let expand = regions.expand;
+ let full = regions.current.y;
+ let rcols = vec![Length::zero(); cols.len()];
+ let lrows = vec![];
+
// We use the regions for auto row measurement. Since at that moment,
// columns are already sized, we can enable horizontal expansion.
- let expand = regions.expand;
regions.expand = Spec::new(true, false);
Self {
children: &grid.children,
- expand,
- rcols: vec![Length::zero(); cols.len()],
cols,
rows,
- full: regions.current.y,
regions,
+ rcols,
+ lrows,
+ expand,
+ full,
used: Size::zero(),
fr: Fractional::zero(),
- lrows: vec![],
cts: Constraints::new(expand),
finished: vec![],
}
diff --git a/src/library/heading.rs b/src/library/heading.rs
index a0b787f3..f2ed3194 100644
--- a/src/library/heading.rs
+++ b/src/library/heading.rs
@@ -16,7 +16,7 @@ pub struct HeadingNode {
#[properties]
impl HeadingNode {
/// The heading's font family.
- pub const FAMILY: Smart<String> = Smart::Auto;
+ pub const FAMILY: Smart<FontFamily> = Smart::Auto;
/// The fill color of heading in the text. Just the surrounding text color
/// if `auto`.
pub const FILL: Smart<Paint> = Smart::Auto;
@@ -25,7 +25,7 @@ impl HeadingNode {
impl Construct for HeadingNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
Ok(Node::block(Self {
- child: args.expect::<Node>("body")?.into_block(),
+ child: args.expect("body")?,
level: args.named("level")?.unwrap_or(1),
}))
}
@@ -50,8 +50,9 @@ impl Layout for HeadingNode {
ctx.styles.set(TextNode::SIZE, Relative::new(upscale).into());
if let Smart::Custom(family) = ctx.styles.get_ref(Self::FAMILY) {
- let list: Vec<_> = std::iter::once(FontFamily::named(family))
- .chain(ctx.styles.get_ref(TextNode::FAMILY_LIST).iter().cloned())
+ let list = std::iter::once(family)
+ .chain(ctx.styles.get_ref(TextNode::FAMILY_LIST))
+ .cloned()
.collect();
ctx.styles.set(TextNode::FAMILY_LIST, list);
}
diff --git a/src/library/list.rs b/src/library/list.rs
index f407d8e9..765cc22b 100644
--- a/src/library/list.rs
+++ b/src/library/list.rs
@@ -26,12 +26,7 @@ impl<L: Labelling> Construct for ListNode<L> {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
Ok(args
.all()
- .map(|node: Node| {
- Node::block(Self {
- child: node.into_block(),
- labelling: L::default(),
- })
- })
+ .map(|child: PackedNode| Node::block(Self { child, labelling: L::default() }))
.sum())
}
}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 61d3ccc0..0cdabcb0 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -193,3 +193,9 @@ castable! {
Expected: "string",
Value::Str(string) => string.into(),
}
+
+castable! {
+ PackedNode,
+ Expected: "node",
+ Value::Node(node) => node.into_block(),
+}
diff --git a/src/library/pad.rs b/src/library/pad.rs
index 70d88b41..96da7a0a 100644
--- a/src/library/pad.rs
+++ b/src/library/pad.rs
@@ -9,7 +9,7 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let top = args.named("top")?;
let right = args.named("right")?;
let bottom = args.named("bottom")?;
- let body: Node = args.expect("body")?;
+ let body: PackedNode = args.expect("body")?;
let padding = Sides::new(
left.or(all).unwrap_or_default(),
top.or(all).unwrap_or_default(),
@@ -17,7 +17,7 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
bottom.or(all).unwrap_or_default(),
);
- Ok(Value::block(body.into_block().padded(padding)))
+ Ok(Value::block(body.padded(padding)))
}
/// A node that adds padding to its child.
diff --git a/src/library/page.rs b/src/library/page.rs
index 00f2dfc6..520cdaef 100644
--- a/src/library/page.rs
+++ b/src/library/page.rs
@@ -44,8 +44,8 @@ impl PageNode {
impl Construct for PageNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
Ok(Node::Page(Self {
- child: args.expect::<Node>("body")?.into_block(),
styles: Styles::new(),
+ child: args.expect("body")?,
}))
}
}
@@ -114,6 +114,7 @@ impl PageNode {
bottom: ctx.styles.get(Self::BOTTOM).unwrap_or(default.bottom),
};
+ // Realize columns with columns node.
let columns = ctx.styles.get(Self::COLUMNS);
let child = if columns.get() > 1 {
ColumnsNode {
@@ -126,14 +127,14 @@ impl PageNode {
self.child.clone()
};
- // Pad the child.
- let padded = PadNode { child, padding }.pack();
+ // Realize margins with padding node.
+ let child = PadNode { child, padding }.pack();
// Layout the child.
let expand = size.map(Length::is_finite);
let regions = Regions::repeat(size, size, expand);
let mut frames: Vec<_> =
- padded.layout(ctx, &regions).into_iter().map(|c| c.item).collect();
+ child.layout(ctx, &regions).into_iter().map(|c| c.item).collect();
// Add background fill if requested.
if let Some(fill) = ctx.styles.get(Self::FILL) {
@@ -238,12 +239,12 @@ macro_rules! papers {
}
impl FromStr for Paper {
- type Err = ParsePaperError;
+ type Err = PaperError;
fn from_str(name: &str) -> Result<Self, Self::Err> {
match name.to_lowercase().as_str() {
$($($pats)* => Ok(Self::$var),)*
- _ => Err(ParsePaperError),
+ _ => Err(PaperError),
}
}
}
@@ -413,12 +414,12 @@ castable! {
/// The error when parsing a [`Paper`] from a string fails.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub struct ParsePaperError;
+pub struct PaperError;
-impl Display for ParsePaperError {
+impl Display for PaperError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad("invalid paper name")
}
}
-impl std::error::Error for ParsePaperError {}
+impl std::error::Error for PaperError {}
diff --git a/src/library/par.rs b/src/library/par.rs
index 2c12f9f6..2bedc98b 100644
--- a/src/library/par.rs
+++ b/src/library/par.rs
@@ -30,7 +30,7 @@ impl ParNode {
impl Construct for ParNode {
fn construct(_: &mut EvalContext, args: &mut Args) -> TypResult<Node> {
// Lift to a block so that it doesn't merge with adjacent stuff.
- Ok(Node::Block(args.expect::<Node>("body")?.into_block()))
+ Ok(Node::Block(args.expect("body")?))
}
}
@@ -60,10 +60,8 @@ impl Set for ParNode {
bail!(span, "must be horizontal");
}
Some(v)
- } else if let Some(dir) = dir {
- Some(if dir == Dir::LTR { Align::Left } else { Align::Right })
} else {
- None
+ dir.map(|dir| dir.start().into())
};
styles.set_opt(Self::DIR, dir);
@@ -85,7 +83,8 @@ impl Layout for ParNode {
let text = self.collect_text();
// Find out the BiDi embedding levels.
- let bidi = BidiInfo::new(&text, Level::from_dir(ctx.styles.get(Self::DIR)));
+ let level = Level::from_dir(ctx.styles.get(Self::DIR));
+ let bidi = BidiInfo::new(&text, level);
// Prepare paragraph layout by building a representation on which we can
// do line breaking without layouting each and every line from scratch.
@@ -255,7 +254,7 @@ impl<'a> ParLayouter<'a> {
let subrange = start .. cursor;
let text = &bidi.text[subrange.clone()];
let styles = node.styles.chain(&ctx.styles);
- let shaped = shape(&mut ctx.fonts, text, styles, level.dir());
+ let shaped = shape(ctx.fonts, text, styles, level.dir());
items.push(ParItem::Text(shaped));
ranges.push(subrange);
}
@@ -446,7 +445,7 @@ impl<'a> LineLayout<'a> {
// empty string.
if !range.is_empty() || rest.is_empty() {
// Reshape that part.
- let reshaped = shaped.reshape(&mut ctx.fonts, range);
+ let reshaped = shaped.reshape(ctx.fonts, range);
last = Some(ParItem::Text(reshaped));
}
@@ -467,7 +466,7 @@ impl<'a> LineLayout<'a> {
// Reshape if necessary.
if range.len() < shaped.text.len() {
if !range.is_empty() {
- let reshaped = shaped.reshape(&mut ctx.fonts, range);
+ let reshaped = shaped.reshape(ctx.fonts, range);
first = Some(ParItem::Text(reshaped));
}
@@ -531,7 +530,7 @@ impl<'a> LineLayout<'a> {
match item {
ParItem::Absolute(v) => offset += *v,
ParItem::Fractional(v) => offset += v.resolve(self.fr, remaining),
- ParItem::Text(shaped) => position(shaped.build(&ctx.fonts)),
+ ParItem::Text(shaped) => position(shaped.build(ctx.fonts)),
ParItem::Frame(frame) => position(frame.clone()),
}
}
diff --git a/src/library/placed.rs b/src/library/placed.rs
index bdf3e2cd..5d98edc4 100644
--- a/src/library/placed.rs
+++ b/src/library/placed.rs
@@ -8,9 +8,9 @@ pub fn place(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let aligns = args.find().unwrap_or(Spec::new(Some(Align::Left), None));
let tx = args.named("dx")?.unwrap_or_default();
let ty = args.named("dy")?.unwrap_or_default();
- let body: Node = args.expect("body")?;
+ let body: PackedNode = args.expect("body")?;
Ok(Value::block(PlacedNode(
- body.into_block().moved(Point::new(tx, ty)).aligned(aligns),
+ body.moved(Point::new(tx, ty)).aligned(aligns),
)))
}
diff --git a/src/library/shape.rs b/src/library/shape.rs
index 3eb1a794..15a857ef 100644
--- a/src/library/shape.rs
+++ b/src/library/shape.rs
@@ -79,9 +79,7 @@ fn shape_impl(
}
// The shape's contents.
- let child = args
- .find()
- .map(|body: Node| body.into_block().padded(Sides::splat(padding)));
+ let child = args.find().map(|body: PackedNode| body.padded(Sides::splat(padding)));
Ok(Value::inline(
ShapeNode { kind, fill, stroke, child }
diff --git a/src/library/sized.rs b/src/library/sized.rs
index 49b515cf..81ca69c2 100644
--- a/src/library/sized.rs
+++ b/src/library/sized.rs
@@ -6,16 +6,14 @@ use super::prelude::*;
pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let width = args.named("width")?;
let height = args.named("height")?;
- let body: Node = args.find().unwrap_or_default();
- Ok(Value::inline(
- body.into_block().sized(Spec::new(width, height)),
- ))
+ let body: PackedNode = args.find().unwrap_or_default();
+ Ok(Value::inline(body.sized(Spec::new(width, height))))
}
/// `block`: Place content into the flow.
pub fn block(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
- let body: Node = args.find().unwrap_or_default();
- Ok(Value::block(body.into_block()))
+ let body: PackedNode = args.find().unwrap_or_default();
+ Ok(Value::block(body))
}
/// A node that sizes its child.
diff --git a/src/library/stack.rs b/src/library/stack.rs
index dfe5e245..d7748378 100644
--- a/src/library/stack.rs
+++ b/src/library/stack.rs
@@ -1,33 +1,15 @@
//! Side-by-side layout of nodes along an axis.
-use std::fmt::{self, Debug, Formatter};
-
use super::prelude::*;
use super::{AlignNode, SpacingKind, SpacingNode};
/// `stack`: Stack children along an axis.
pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
- let dir = args.named("dir")?.unwrap_or(Dir::TTB);
- let spacing = args.named("spacing")?;
-
- let mut children = vec![];
- let mut deferred = None;
-
- // Build the list of stack children.
- for child in args.all() {
- match child {
- StackChild::Spacing(_) => deferred = None,
- StackChild::Node(_) => {
- if let Some(v) = deferred {
- children.push(StackChild::spacing(v));
- }
- deferred = spacing;
- }
- }
- children.push(child);
- }
-
- Ok(Value::block(StackNode { dir, children }))
+ Ok(Value::block(StackNode {
+ dir: args.named("dir")?.unwrap_or(Dir::TTB),
+ spacing: args.named("spacing")?,
+ children: args.all().collect(),
+ }))
}
/// A node that stacks its children.
@@ -35,6 +17,8 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
pub struct StackNode {
/// The stacking direction.
pub dir: Dir,
+ /// The spacing between non-spacing children.
+ pub spacing: Option<SpacingKind>,
/// The children to be stacked.
pub children: Vec<StackChild>,
}
@@ -45,7 +29,7 @@ impl Layout for StackNode {
ctx: &mut LayoutContext,
regions: &Regions,
) -> Vec<Constrained<Rc<Frame>>> {
- StackLayouter::new(self, regions).layout(ctx)
+ StackLayouter::new(self, regions.clone()).layout(ctx)
}
}
@@ -58,9 +42,8 @@ pub enum StackChild {
Node(PackedNode),
}
-impl StackChild {
- /// Create a spacing node from a spacing kind.
- pub fn spacing(kind: SpacingKind) -> Self {
+impl From<SpacingKind> for StackChild {
+ fn from(kind: SpacingKind) -> Self {
Self::Spacing(SpacingNode { kind, styles: Styles::new() })
}
}
@@ -77,23 +60,27 @@ impl Debug for StackChild {
castable! {
StackChild,
Expected: "linear, fractional or template",
- Value::Length(v) => Self::spacing(SpacingKind::Linear(v.into())),
- Value::Relative(v) => Self::spacing(SpacingKind::Linear(v.into())),
- Value::Linear(v) => Self::spacing(SpacingKind::Linear(v)),
- Value::Fractional(v) => Self::spacing(SpacingKind::Fractional(v)),
+ Value::Length(v) => SpacingKind::Linear(v.into()).into(),
+ Value::Relative(v) => SpacingKind::Linear(v.into()).into(),
+ Value::Linear(v) => SpacingKind::Linear(v).into(),
+ Value::Fractional(v) => SpacingKind::Fractional(v).into(),
Value::Node(v) => Self::Node(v.into_block()),
}
/// Performs stack layout.
struct StackLayouter<'a> {
- /// The stack node to layout.
- stack: &'a StackNode,
- /// The axis of the block direction.
+ /// The flow node to layout.
+ children: &'a [StackChild],
+ /// The stacking direction.
+ dir: Dir,
+ /// The axis of the stacking direction.
axis: SpecAxis,
- /// Whether the stack should expand to fill the region.
- expand: Spec<bool>,
+ /// The spacing between non-spacing children.
+ spacing: Option<SpacingKind>,
/// The regions to layout children into.
regions: Regions,
+ /// Whether the stack should expand to fill the region.
+ expand: Spec<bool>,
/// The full size of `regions.current` that was available before we started
/// subtracting.
full: Size,
@@ -119,21 +106,23 @@ enum StackItem {
impl<'a> StackLayouter<'a> {
/// Create a new stack layouter.
- fn new(stack: &'a StackNode, regions: &Regions) -> Self {
- let axis = stack.dir.axis();
+ fn new(stack: &'a StackNode, mut regions: Regions) -> Self {
+ let dir = stack.dir;
+ let axis = dir.axis();
let expand = regions.expand;
let full = regions.current;
// Disable expansion along the block axis for children.
- let mut regions = regions.clone();
regions.expand.set(axis, false);
Self {
- stack,
+ children: &stack.children,
+ dir,
axis,
+ spacing: stack.spacing,
+ regions,
expand,
full,
- regions,
used: Gen::zero(),
fr: Fractional::zero(),
items: vec![],
@@ -143,21 +132,26 @@ impl<'a> StackLayouter<'a> {
/// Layout all children.
fn layout(mut self, ctx: &mut LayoutContext) -> Vec<Constrained<Rc<Frame>>> {
- for child in &self.stack.children {
+ // Spacing to insert before the next node.
+ let mut deferred = None;
+
+ for child in self.children {
match child {
- StackChild::Spacing(node) => match node.kind {
- SpacingKind::Linear(v) => self.layout_absolute(v),
- SpacingKind::Fractional(v) => {
- self.items.push(StackItem::Fractional(v));
- self.fr += v;
- }
- },
+ StackChild::Spacing(node) => {
+ self.layout_spacing(node.kind);
+ deferred = None;
+ }
StackChild::Node(node) => {
+ if let Some(kind) = deferred {
+ self.layout_spacing(kind);
+ }
+
if self.regions.is_full() {
self.finish_region();
}
self.layout_node(ctx, node);
+ deferred = self.spacing;
}
}
}
@@ -166,6 +160,17 @@ impl<'a> StackLayouter<'a> {
self.finished
}
+ /// Layout spacing.
+ fn layout_spacing(&mut self, spacing: SpacingKind) {
+ match spacing {
+ SpacingKind::Linear(v) => self.layout_absolute(v),
+ SpacingKind::Fractional(v) => {
+ self.items.push(StackItem::Fractional(v));
+ self.fr += v;
+ }
+ }
+ }
+
/// Layout absolute spacing.
fn layout_absolute(&mut self, amount: Linear) {
// Resolve the linear, limiting it to the remaining available space.
@@ -183,7 +188,7 @@ impl<'a> StackLayouter<'a> {
let align = node
.downcast::<AlignNode>()
.and_then(|node| node.aligns.get(self.axis))
- .unwrap_or(self.stack.dir.start().into());
+ .unwrap_or(self.dir.start().into());
let frames = node.layout(ctx, &self.regions);
let len = frames.len();
@@ -218,7 +223,7 @@ impl<'a> StackLayouter<'a> {
let mut output = Frame::new(size);
let mut cursor = Length::zero();
- let mut ruler: Align = self.stack.dir.start().into();
+ let mut ruler: Align = self.dir.start().into();
// Place all frames.
for item in self.items.drain(..) {
@@ -230,7 +235,7 @@ impl<'a> StackLayouter<'a> {
cursor += v.resolve(self.fr, remaining);
}
StackItem::Frame(frame, align) => {
- if self.stack.dir.is_positive() {
+ if self.dir.is_positive() {
ruler = ruler.max(align);
} else {
ruler = ruler.min(align);
@@ -240,7 +245,7 @@ impl<'a> StackLayouter<'a> {
let parent = size.get(self.axis);
let child = frame.size.get(self.axis);
let block = ruler.resolve(parent - self.used.main)
- + if self.stack.dir.is_positive() {
+ + if self.dir.is_positive() {
cursor
} else {
self.used.main - child - cursor
diff --git a/src/library/text.rs b/src/library/text.rs
index df71fec9..26e949fc 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -173,13 +173,6 @@ pub enum FontFamily {
Named(NamedFamily),
}
-impl FontFamily {
- /// Create a named font family variant, directly from a string.
- pub fn named(string: &str) -> Self {
- Self::Named(NamedFamily::new(string))
- }
-}
-
impl Debug for FontFamily {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
@@ -193,13 +186,13 @@ impl Debug for FontFamily {
dynamic! {
FontFamily: "font family",
- Value::Str(string) => Self::named(&string),
+ Value::Str(string) => Self::Named(NamedFamily::new(&string)),
}
castable! {
Vec<FontFamily>,
Expected: "string, generic family or array thereof",
- Value::Str(string) => vec![FontFamily::named(&string)],
+ Value::Str(string) => vec![FontFamily::Named(NamedFamily::new(&string))],
Value::Array(values) => {
values.into_iter().filter_map(|v| v.cast().ok()).collect()
},
diff --git a/src/library/transform.rs b/src/library/transform.rs
index ef468d7b..03f0a84c 100644
--- a/src/library/transform.rs
+++ b/src/library/transform.rs
@@ -28,15 +28,13 @@ pub fn rotate(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
}
fn transform_impl(args: &mut Args, transform: Transform) -> TypResult<Value> {
- let body: Node = args.expect("body")?;
+ let body: PackedNode = args.expect("body")?;
let origin = args
.named("origin")?
.unwrap_or(Spec::splat(None))
.unwrap_or(Align::CENTER_HORIZON);
- Ok(Value::inline(
- body.into_block().transformed(transform, origin),
- ))
+ Ok(Value::inline(body.transformed(transform, origin)))
}
/// A node that transforms its child without affecting layout.