summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-10-13 14:15:17 +0200
committerLaurenz <laurmaedje@gmail.com>2021-10-23 20:22:47 +0200
commit5f4dde0a6b32c7620b29af30f69591cf3995af9b (patch)
tree0c56fc286620b03b51d8555e37190c53c008ed98
parent9ac125dea8d6ea6cc01814d04413225845b69d65 (diff)
Remove inline alignment from stack
The current inline alignment is very broken and leads to lots of subtle weirdness. Getting rid of it simplifies the stack's interface a lot. At a later point either: - inline alignment will be added back in a better way, or - all nodes will be able to expand or align themselves, meaning that the stack's children take care of their alignment
-rw-r--r--src/eval/template.rs21
-rw-r--r--src/eval/walk.rs8
-rw-r--r--src/layout/stack.rs41
-rw-r--r--src/library/layout.rs22
-rw-r--r--tests/ref/layout/stack.pngbin371 -> 319 bytes
-rw-r--r--tests/typ/layout/stack.typ3
6 files changed, 33 insertions, 62 deletions
diff --git a/src/eval/template.rs b/src/eval/template.rs
index 0ea312e5..59fe293a 100644
--- a/src/eval/template.rs
+++ b/src/eval/template.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
use super::Str;
use crate::diag::StrResult;
-use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size};
+use crate::geom::{Align, Dir, GenAxis, Length, Linear, Sides, Size};
use crate::layout::{
Decoration, LayoutNode, LayoutTree, PadNode, PageRun, ParChild, ParNode, StackChild,
StackNode,
@@ -335,8 +335,7 @@ impl Builder {
/// Push a block node into the active stack, finishing the active paragraph.
fn block(&mut self, node: impl Into<LayoutNode>) {
self.parbreak();
- let aligns = self.style.aligns;
- self.stack.push(StackChild::Any(node.into(), aligns));
+ self.stack.push(StackChild::Any(node.into(), self.style.aligns.block));
self.parbreak();
}
@@ -407,7 +406,7 @@ impl PageBuilder {
}
struct StackBuilder {
- dirs: Gen<Dir>,
+ dir: Dir,
children: Vec<StackChild>,
last: Last<StackChild>,
par: ParBuilder,
@@ -416,7 +415,7 @@ struct StackBuilder {
impl StackBuilder {
fn new(style: &Style) -> Self {
Self {
- dirs: Gen::new(style.dir, Dir::TTB),
+ dir: Dir::TTB,
children: vec![],
last: Last::None,
par: ParBuilder::new(style),
@@ -445,17 +444,17 @@ impl StackBuilder {
}
fn build(self) -> StackNode {
- let Self { dirs, mut children, par, mut last } = self;
+ let Self { dir, mut children, par, mut last } = self;
if let Some(par) = par.build() {
children.extend(last.any());
children.push(par);
}
- StackNode { dirs, children }
+ StackNode { dir, children }
}
}
struct ParBuilder {
- aligns: Gen<Align>,
+ align: Align,
dir: Dir,
line_spacing: Length,
children: Vec<ParChild>,
@@ -465,7 +464,7 @@ struct ParBuilder {
impl ParBuilder {
fn new(style: &Style) -> Self {
Self {
- aligns: style.aligns,
+ align: style.aligns.block,
dir: style.dir,
line_spacing: style.line_spacing(),
children: vec![],
@@ -508,10 +507,10 @@ impl ParBuilder {
}
fn build(self) -> Option<StackChild> {
- let Self { aligns, dir, line_spacing, children, .. } = self;
+ let Self { align, dir, line_spacing, children, .. } = self;
(!children.is_empty()).then(|| {
let node = ParNode { dir, line_spacing, children };
- StackChild::Any(node.into(), aligns)
+ StackChild::Any(node.into(), align)
})
}
}
diff --git a/src/eval/walk.rs b/src/eval/walk.rs
index 90361141..b76300ec 100644
--- a/src/eval/walk.rs
+++ b/src/eval/walk.rs
@@ -2,7 +2,7 @@ use std::rc::Rc;
use super::{Eval, EvalContext, Str, Template, Value};
use crate::diag::TypResult;
-use crate::geom::{Dir, Gen};
+use crate::geom::Align;
use crate::layout::{ParChild, ParNode, StackChild, StackNode};
use crate::syntax::*;
use crate::util::BoolExt;
@@ -117,11 +117,11 @@ fn walk_item(ctx: &mut EvalContext, label: Str, body: Template) {
)],
};
StackNode {
- dirs: Gen::new(Dir::TTB, style.dir),
+ dir: style.dir,
children: vec![
- StackChild::Any(label.into(), Gen::default()),
+ StackChild::Any(label.into(), Align::Start),
StackChild::Spacing((style.text.size / 2.0).into()),
- StackChild::Any(body.to_stack(&style).into(), Gen::default()),
+ StackChild::Any(body.to_stack(&style).into(), Align::Start),
],
}
});
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index e3416e6b..765fb7ab 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -6,11 +6,8 @@ use super::*;
#[derive(Debug)]
#[cfg_attr(feature = "layout-cache", derive(Hash))]
pub struct StackNode {
- /// The inline and block directions of this stack.
- ///
- /// The children are stacked along the block direction. The inline direction
- /// is required for aligning the children.
- pub dirs: Gen<Dir>,
+ /// The stacking direction.
+ pub dir: Dir,
/// The nodes to be stacked.
pub children: Vec<StackChild>,
}
@@ -21,7 +18,7 @@ pub enum StackChild {
/// Spacing between other nodes.
Spacing(Linear),
/// Any child node and how to align it in the stack.
- Any(LayoutNode, Gen<Align>),
+ Any(LayoutNode, Align),
}
impl Layout for StackNode {
@@ -72,7 +69,7 @@ struct StackLayouter<'a> {
overflowing: bool,
/// Offset, alignment and frame for all children that fit into the current
/// region. The exact positions are not known yet.
- frames: Vec<(Length, Gen<Align>, Rc<Frame>)>,
+ frames: Vec<(Length, Align, Rc<Frame>)>,
/// Finished frames for previous regions.
finished: Vec<Constrained<Rc<Frame>>>,
}
@@ -80,7 +77,7 @@ struct StackLayouter<'a> {
impl<'a> StackLayouter<'a> {
/// Create a new stack layouter.
fn new(stack: &'a StackNode, mut regions: Regions) -> Self {
- let block = stack.dirs.block.axis();
+ let block = stack.dir.axis();
let full = regions.current;
let expand = regions.expand;
@@ -107,14 +104,14 @@ impl<'a> StackLayouter<'a> {
for child in &self.stack.children {
match *child {
StackChild::Spacing(amount) => self.space(amount),
- StackChild::Any(ref node, aligns) => {
+ StackChild::Any(ref node, align) => {
let nodes = node.layout(ctx, &self.regions);
let len = nodes.len();
for (i, frame) in nodes.into_iter().enumerate() {
if i + 1 < len {
self.constraints.exact = self.full.to_spec().map(Some);
}
- self.push_frame(frame.item, aligns);
+ self.push_frame(frame.item, align);
}
}
}
@@ -142,11 +139,11 @@ impl<'a> StackLayouter<'a> {
/// Push a frame into the current or next fitting region, finishing regions
/// if necessary.
- fn push_frame(&mut self, frame: Rc<Frame>, aligns: Gen<Align>) {
+ fn push_frame(&mut self, frame: Rc<Frame>, align: Align) {
let size = frame.size.to_gen(self.block);
// Don't allow `Start` after `End` in the same region.
- if aligns.block < self.ruler {
+ if align < self.ruler {
self.finish_region();
}
@@ -172,10 +169,10 @@ impl<'a> StackLayouter<'a> {
let offset = self.used.block;
self.used.block += size.block;
self.used.inline.set_max(size.inline);
- self.ruler = aligns.block;
+ self.ruler = align;
// Remember the frame with offset and alignment.
- self.frames.push((offset, aligns, frame));
+ self.frames.push((offset, align, frame));
}
/// Finish the frame for one region.
@@ -211,20 +208,14 @@ impl<'a> StackLayouter<'a> {
let mut first = true;
// Place all frames.
- for (offset, aligns, frame) in self.frames.drain(..) {
+ for (offset, align, frame) in self.frames.drain(..) {
let stack_size = size.to_gen(self.block);
let child_size = frame.size.to_gen(self.block);
- // Align along the inline axis.
- let inline = aligns.inline.resolve(
- self.stack.dirs.inline,
- Length::zero() .. stack_size.inline - child_size.inline,
- );
-
// Align along the block axis.
- let block = aligns.block.resolve(
- self.stack.dirs.block,
- if self.stack.dirs.block.is_positive() {
+ let block = align.resolve(
+ self.stack.dir,
+ if self.stack.dir.is_positive() {
offset .. stack_size.block - self.used.block + offset
} else {
let offset_with_self = offset + child_size.block;
@@ -233,7 +224,7 @@ impl<'a> StackLayouter<'a> {
},
);
- let pos = Gen::new(inline, block).to_point(self.block);
+ let pos = Gen::new(Length::zero(), block).to_point(self.block);
// The baseline of the stack is that of the first frame.
if first {
diff --git a/src/library/layout.rs b/src/library/layout.rs
index c8b22f88..efa012b9 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -204,27 +204,11 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
Value::Template(v) => Self::Any(v),
}
- let dir = args.named("dir")?;
+ let dir = args.named("dir")?.unwrap_or(Dir::TTB);
let spacing = args.named("spacing")?;
let list: Vec<Child> = args.all().collect();
Ok(Value::Template(Template::from_block(move |style| {
- let mut dirs = Gen::new(style.dir, dir.unwrap_or(Dir::TTB));
-
- // If the directions become aligned, fix up the inline direction since
- // that's the one that is not user-defined.
- if dirs.inline.axis() == dirs.block.axis() {
- dirs.inline = Dir::TTB;
- }
-
- // Use the current alignments for all children, but take care to apply
- // them to the correct axes (by swapping them if the stack axes are
- // different from the style axes).
- let mut aligns = style.aligns;
- if dirs.inline.axis() != style.dir.axis() {
- aligns = Gen::new(aligns.block, aligns.inline);
- }
-
let mut children = vec![];
let mut delayed = None;
@@ -241,13 +225,13 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
}
let node = template.to_stack(style).into();
- children.push(StackChild::Any(node, aligns));
+ children.push(StackChild::Any(node, style.aligns.block));
delayed = spacing;
}
}
}
- StackNode { dirs, children }
+ StackNode { dir, children }
})))
}
diff --git a/tests/ref/layout/stack.png b/tests/ref/layout/stack.png
index 13438d07..78f7ed77 100644
--- a/tests/ref/layout/stack.png
+++ b/tests/ref/layout/stack.png
Binary files differ
diff --git a/tests/typ/layout/stack.typ b/tests/typ/layout/stack.typ
index a6e7e001..b8d8a09d 100644
--- a/tests/typ/layout/stack.typ
+++ b/tests/typ/layout/stack.typ
@@ -20,9 +20,6 @@
#stack(dir: btt, ..items)
#pagebreak()
-// Currently stack works like flexbox apparently.
-#stack(dir: ltr, ..items)
-
---
// Test spacing.
#page(width: 50pt, margins: 0pt)