summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/layout/mod.rs6
-rw-r--r--src/layout/stacked.rs10
-rw-r--r--src/layout/tree.rs32
-rw-r--r--src/library/align.rs5
-rw-r--r--tests/layouts/align.typ9
-rw-r--r--tests/layouts/pagebreaks.typ2
-rw-r--r--tests/layouts/shakespeare.typ7
7 files changed, 42 insertions, 29 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index b0fba4f2..a5dfa0ad 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -149,10 +149,7 @@ pub struct LayoutSpace {
impl LayoutSpace {
/// The actually usable area (dimensions minus padding).
pub fn usable(&self) -> Size2D {
- Size2D {
- x: self.dimensions.x - self.padding.left - self.padding.right,
- y: self.dimensions.y - self.padding.top - self.padding.bottom,
- }
+ self.dimensions.unpadded(self.padding)
}
}
@@ -161,6 +158,7 @@ impl LayoutSpace {
pub enum Alignment {
Left,
Right,
+ Center,
}
/// The error type for layouting.
diff --git a/src/layout/stacked.rs b/src/layout/stacked.rs
index 367a03d7..3a29f722 100644
--- a/src/layout/stacked.rs
+++ b/src/layout/stacked.rs
@@ -73,6 +73,7 @@ impl StackLayouter {
let position = match self.space.alignment {
Alignment::Left => self.cursor,
Alignment::Right => self.cursor - Size2D::with_x(layout.dimensions.x),
+ Alignment::Center => self.cursor - Size2D::with_x(layout.dimensions.x / 2),
};
self.cursor.y += layout.dimensions.y;
@@ -172,9 +173,9 @@ impl StackLayouter {
}
}
- /// Whether this layouter contains any items.
- pub fn is_empty(&self) -> bool {
- self.layouts.is_empty() && self.actions.is_empty()
+ /// Whether the active space of this layouter contains no content.
+ pub fn current_space_is_empty(&self) -> bool {
+ !self.started || self.actions.is_empty()
}
fn overflows(&self, dimensions: Size2D) -> bool {
@@ -185,7 +186,7 @@ impl StackLayouter {
fn start_dimensions(space: LayoutSpace) -> Size2D {
match space.alignment {
Alignment::Left => Size2D::zero(),
- Alignment::Right => Size2D::with_x(space.usable().x),
+ Alignment::Right | Alignment::Center => Size2D::with_x(space.usable().x),
}
}
@@ -197,6 +198,7 @@ fn start_cursor(space: LayoutSpace) -> Size2D {
x: match space.alignment {
Alignment::Left => space.padding.left,
Alignment::Right => space.dimensions.x - space.padding.right,
+ Alignment::Center => space.padding.left + (space.usable().x / 2),
},
y: space.padding.top,
}
diff --git a/src/layout/tree.rs b/src/layout/tree.rs
index c8695e83..7feed610 100644
--- a/src/layout/tree.rs
+++ b/src/layout/tree.rs
@@ -47,8 +47,14 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
// Finish the current flex layouting process.
Node::Newline => {
- let space = paragraph_spacing(&self.style);
- self.layout_flex(space)?;
+ self.layout_flex()?;
+
+ if !self.stack.current_space_is_empty() {
+ let space = paragraph_spacing(&self.style);
+ self.stack.add_space(space)?;
+ }
+
+ self.start_new_flex();
}
// Toggle the text styles.
@@ -65,11 +71,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
/// Finish the layout.
fn finish(mut self) -> LayoutResult<MultiLayout> {
- // If there are remainings, add them to the layout.
- if !self.flex.is_empty() {
- self.layout_flex(Size::zero())?;
- }
-
+ self.layout_flex()?;
self.stack.finish()
}
@@ -93,22 +95,24 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
}
/// Finish the current flex layout and add it the stack.
- fn layout_flex(&mut self, after_space: Size) -> LayoutResult<()> {
+ fn layout_flex(&mut self) -> LayoutResult<()> {
if self.flex.is_empty() {
return Ok(());
}
let layouts = self.flex.finish()?;
self.stack.add_many(layouts)?;
- self.stack.add_space(after_space)?;
+ Ok(())
+ }
+
+ /// Start a new flex layout.
+ fn start_new_flex(&mut self) {
let mut ctx = self.flex.ctx();
ctx.space.dimensions = self.stack.remaining();
ctx.flex_spacing = flex_spacing(&self.style);
self.flex = FlexLayouter::new(ctx);
-
- Ok(())
}
/// Layout a function.
@@ -118,12 +122,12 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
ctx.space.dimensions = self.stack.remaining();
ctx.space.padding = SizeBox::zero();
- ctx.space.shrink_to_fit = false;
+ ctx.space.shrink_to_fit = true;
if let Some(space) = ctx.extra_space.as_mut() {
- space.dimensions = space.dimensions.unpadded(space.padding);
+ space.dimensions = space.usable();
space.padding = SizeBox::zero();
- space.shrink_to_fit = false;
+ space.shrink_to_fit = true;
}
let commands = func.body.layout(ctx)?;
diff --git a/src/library/align.rs b/src/library/align.rs
index 4dc5f53c..f81bae31 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -19,6 +19,7 @@ impl Function for AlignFunc {
match ident.as_str() {
"left" => Alignment::Left,
"right" => Alignment::Right,
+ "center" => Alignment::Center,
s => return err(format!("invalid alignment specifier: '{}'", s)),
}
} else {
@@ -40,6 +41,10 @@ impl Function for AlignFunc {
fn layout(&self, mut ctx: LayoutContext) -> LayoutResult<FuncCommands> {
if let Some(body) = &self.body {
ctx.space.alignment = self.alignment;
+ if let Some(space) = ctx.extra_space.as_mut() {
+ space.alignment = self.alignment;
+ }
+
let layouts = layout_tree(body, ctx)?;
let mut commands = FuncCommands::new();
diff --git a/tests/layouts/align.typ b/tests/layouts/align.typ
new file mode 100644
index 00000000..8cad240c
--- /dev/null
+++ b/tests/layouts/align.typ
@@ -0,0 +1,9 @@
+{size:150pt*206pt}
+
+[align: left][Left: {lorem:20}]
+
+[align: right][Right: {lorem:20}]
+
+[align: center][Center: {lorem:80}]
+
+[align: left][Left: {lorem:20}]
diff --git a/tests/layouts/pagebreaks.typ b/tests/layouts/pagebreaks.typ
index 6887613f..00684f56 100644
--- a/tests/layouts/pagebreaks.typ
+++ b/tests/layouts/pagebreaks.typ
@@ -1,2 +1,2 @@
{size:200pt*200pt}
-{lorem:400}
+{lorem:300}
diff --git a/tests/layouts/shakespeare.typ b/tests/layouts/shakespeare.typ
index 09edd361..19450ce4 100644
--- a/tests/layouts/shakespeare.typ
+++ b/tests/layouts/shakespeare.typ
@@ -1,8 +1,3 @@
-// Basic unboxed
-{include:shakespeare.tpl}
-
-// Boxed, but still left-aligned
+[align: center][{include:shakespeare.tpl}]
[align: left][{include:shakespeare.tpl}]
-
-// Boxed, and right-aligned
[align: right][{include:shakespeare.tpl}]