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
This commit is contained in:
parent
9ac125dea8
commit
5f4dde0a6b
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -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 }
|
||||
})))
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 319 B |
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user