mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Double-try spaces for functions 🌑🌕
This commit is contained in:
parent
14259c7d09
commit
1eb25f86dd
@ -23,6 +23,7 @@ pub struct FlexLayouter {
|
|||||||
stack: StackLayouter,
|
stack: StackLayouter,
|
||||||
units: Vec<FlexUnit>,
|
units: Vec<FlexUnit>,
|
||||||
|
|
||||||
|
total_usable: Size,
|
||||||
merged_actions: LayoutActionList,
|
merged_actions: LayoutActionList,
|
||||||
merged_dimensions: Size2D,
|
merged_dimensions: Size2D,
|
||||||
max_extent: Size,
|
max_extent: Size,
|
||||||
@ -30,6 +31,8 @@ pub struct FlexLayouter {
|
|||||||
usable: Size,
|
usable: Size,
|
||||||
run: FlexRun,
|
run: FlexRun,
|
||||||
space: Option<Size>,
|
space: Option<Size>,
|
||||||
|
|
||||||
|
last_run_remaining: Size2D,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The context for flex layouting.
|
/// The context for flex layouting.
|
||||||
@ -77,13 +80,16 @@ impl FlexLayouter {
|
|||||||
units: vec![],
|
units: vec![],
|
||||||
stack,
|
stack,
|
||||||
|
|
||||||
|
total_usable: usable,
|
||||||
merged_actions: LayoutActionList::new(),
|
merged_actions: LayoutActionList::new(),
|
||||||
merged_dimensions: Size2D::with_x(usable),
|
merged_dimensions: Size2D::zero(),
|
||||||
max_extent: Size::zero(),
|
max_extent: Size::zero(),
|
||||||
|
|
||||||
usable,
|
usable,
|
||||||
run: FlexRun { content: vec![], size: Size2D::zero() },
|
run: FlexRun { content: vec![], size: Size2D::zero() },
|
||||||
space: None,
|
space: None,
|
||||||
|
|
||||||
|
last_run_remaining: Size2D::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +178,7 @@ impl FlexLayouter {
|
|||||||
fn layout_box(&mut self, boxed: Layout) -> LayoutResult<()> {
|
fn layout_box(&mut self, boxed: Layout) -> LayoutResult<()> {
|
||||||
let size = self.ctx.axes.generalize(boxed.dimensions);
|
let size = self.ctx.axes.generalize(boxed.dimensions);
|
||||||
|
|
||||||
let space = self.space.unwrap_or(Size::zero());
|
if size.x > self.size_left() {
|
||||||
let new_run_size = self.run.size.x + space + size.x;
|
|
||||||
|
|
||||||
if new_run_size > self.usable {
|
|
||||||
self.space = None;
|
self.space = None;
|
||||||
self.finish_run()?;
|
self.finish_run()?;
|
||||||
|
|
||||||
@ -185,7 +188,8 @@ impl FlexLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.stack.finish_layout(true);
|
self.stack.finish_layout(true);
|
||||||
self.usable = self.stack.usable().x;
|
self.total_usable = self.stack.usable().x;
|
||||||
|
self.usable = self.total_usable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,12 +218,16 @@ impl FlexLayouter {
|
|||||||
|
|
||||||
self.usable = match axes.primary.alignment {
|
self.usable = match axes.primary.alignment {
|
||||||
Alignment::Origin =>
|
Alignment::Origin =>
|
||||||
if self.max_extent == Size::zero() { self.usable } else { Size::zero() },
|
if self.max_extent == Size::zero() {
|
||||||
|
self.total_usable
|
||||||
|
} else {
|
||||||
|
Size::zero()
|
||||||
|
},
|
||||||
Alignment::Center => crate::size::max(
|
Alignment::Center => crate::size::max(
|
||||||
self.merged_dimensions.x - 2 * self.max_extent,
|
self.total_usable - 2 * self.max_extent,
|
||||||
Size::zero()
|
Size::zero()
|
||||||
),
|
),
|
||||||
Alignment::End => self.merged_dimensions.x - self.max_extent,
|
Alignment::End => self.total_usable - self.max_extent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,8 +246,6 @@ impl FlexLayouter {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.merged_dimensions.y += self.ctx.flex_spacing;
|
|
||||||
|
|
||||||
let actions = std::mem::replace(&mut self.merged_actions, LayoutActionList::new());
|
let actions = std::mem::replace(&mut self.merged_actions, LayoutActionList::new());
|
||||||
self.stack.add(Layout {
|
self.stack.add(Layout {
|
||||||
dimensions: self.ctx.axes.specialize(self.merged_dimensions),
|
dimensions: self.ctx.axes.specialize(self.merged_dimensions),
|
||||||
@ -247,9 +253,9 @@ impl FlexLayouter {
|
|||||||
debug_render: false,
|
debug_render: false,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.merged_dimensions.y = Size::zero();
|
self.merged_dimensions = Size2D::zero();
|
||||||
self.max_extent = Size::zero();
|
self.max_extent = Size::zero();
|
||||||
self.usable = self.merged_dimensions.x;
|
self.usable = self.total_usable;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -260,7 +266,7 @@ impl FlexLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let factor = if self.ctx.axes.primary.axis.is_positive() { 1 } else { -1 };
|
let factor = if self.ctx.axes.primary.axis.is_positive() { 1 } else { -1 };
|
||||||
let anchor = self.ctx.axes.primary.anchor(self.merged_dimensions.x)
|
let anchor = self.ctx.axes.primary.anchor(self.total_usable)
|
||||||
- self.ctx.axes.primary.anchor(self.run.size.x);
|
- self.ctx.axes.primary.anchor(self.run.size.x);
|
||||||
|
|
||||||
self.max_extent = crate::size::max(self.max_extent, anchor + factor * self.run.size.x);
|
self.max_extent = crate::size::max(self.max_extent, anchor + factor * self.run.size.x);
|
||||||
@ -272,7 +278,17 @@ impl FlexLayouter {
|
|||||||
self.merged_actions.add_layout(position, layout);
|
self.merged_actions.add_layout(position, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.merged_dimensions.y = crate::size::max(self.merged_dimensions.y, self.run.size.y);
|
self.merged_dimensions.x = match self.ctx.axes.primary.alignment {
|
||||||
|
Alignment::Origin => self.run.size.x,
|
||||||
|
Alignment::Center | Alignment::End => self.total_usable,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.merged_dimensions.y = crate::size::max(
|
||||||
|
self.merged_dimensions.y,
|
||||||
|
self.run.size.y + self.ctx.flex_spacing,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.last_run_remaining = Size2D::new(self.size_left(), self.merged_dimensions.y);
|
||||||
self.run.size = Size2D::zero();
|
self.run.size = Size2D::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,10 +297,17 @@ impl FlexLayouter {
|
|||||||
&self.ctx
|
&self.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remaining(&self) -> LayoutResult<LayoutSpaces> {
|
pub fn remaining(&self) -> LayoutResult<(LayoutSpaces, LayoutSpaces)> {
|
||||||
let mut future = self.clone();
|
let mut future = self.clone();
|
||||||
future.finish_box()?;
|
future.finish_box()?;
|
||||||
Ok(future.stack.remaining())
|
|
||||||
|
let stack_spaces = future.stack.remaining();
|
||||||
|
|
||||||
|
let mut flex_spaces = stack_spaces.clone();
|
||||||
|
flex_spaces[0].dimensions.x = future.last_run_remaining.x;
|
||||||
|
flex_spaces[0].dimensions.y += future.last_run_remaining.y;
|
||||||
|
|
||||||
|
Ok((flex_spaces, stack_spaces))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this layouter contains any items.
|
/// Whether this layouter contains any items.
|
||||||
@ -295,4 +318,9 @@ impl FlexLayouter {
|
|||||||
pub fn last_is_space(&self) -> bool {
|
pub fn last_is_space(&self) -> bool {
|
||||||
matches!(self.units.last(), Some(FlexUnit::Space(_)))
|
matches!(self.units.last(), Some(FlexUnit::Space(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn size_left(&self) -> Size {
|
||||||
|
let space = self.space.unwrap_or(Size::zero());
|
||||||
|
self.usable - (self.run.size.x + space)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl StackLayouter {
|
|||||||
layouts: MultiLayout::new(),
|
layouts: MultiLayout::new(),
|
||||||
|
|
||||||
merged_actions: LayoutActionList::new(),
|
merged_actions: LayoutActionList::new(),
|
||||||
merged_dimensions: space.start(),
|
merged_dimensions: Size2D::zero(),
|
||||||
|
|
||||||
boxes: vec![],
|
boxes: vec![],
|
||||||
usable,
|
usable,
|
||||||
|
@ -65,12 +65,24 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
|
|
||||||
/// Layout a function.
|
/// Layout a function.
|
||||||
fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> {
|
fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> {
|
||||||
let commands = func.body.val.layout(LayoutContext {
|
let (flex_spaces, stack_spaces) = self.flex.remaining()?;
|
||||||
|
|
||||||
|
let ctx = |spaces| LayoutContext {
|
||||||
style: &self.style,
|
style: &self.style,
|
||||||
spaces: self.flex.remaining()?,
|
spaces: spaces,
|
||||||
shrink_to_fit: true,
|
shrink_to_fit: true,
|
||||||
.. self.ctx
|
.. self.ctx
|
||||||
})?;
|
};
|
||||||
|
|
||||||
|
// Try putting it in the flex space first, but if that is not enough
|
||||||
|
// space, use the other space.
|
||||||
|
let commands = match func.body.val.layout(ctx(flex_spaces)) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(LayoutError::NotEnoughSpace(_)) => {
|
||||||
|
func.body.val.layout(ctx(stack_spaces))?
|
||||||
|
},
|
||||||
|
e => e?,
|
||||||
|
};
|
||||||
|
|
||||||
for command in commands {
|
for command in commands {
|
||||||
self.execute(command)?;
|
self.execute(command)?;
|
||||||
|
@ -28,16 +28,17 @@ function! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
layout(this, ctx) {
|
layout(this, ctx) {
|
||||||
let mut new_axes = ctx.axes;
|
let mut axes = ctx.axes;
|
||||||
new_axes.primary.alignment = this.alignment;
|
axes.primary.alignment = this.alignment;
|
||||||
|
|
||||||
Ok(match &this.body {
|
Ok(match &this.body {
|
||||||
Some(body) => commands![
|
Some(body) => commands![AddMultiple(
|
||||||
SetAxes(new_axes),
|
layout_tree(body, LayoutContext {
|
||||||
LayoutTree(body),
|
axes,
|
||||||
SetAxes(ctx.axes),
|
.. ctx.clone()
|
||||||
],
|
})?
|
||||||
None => commands![Command::SetAxes(new_axes)]
|
)],
|
||||||
|
None => commands![Command::SetAxes(axes)]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,16 @@ macro_rules! stylefunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
layout(this, ctx) {
|
layout(this, ctx) {
|
||||||
let mut new_style = ctx.style.clone();
|
let mut style = ctx.style.clone();
|
||||||
new_style.toggle_class(FontClass::$ident);
|
style.toggle_class(FontClass::$ident);
|
||||||
|
|
||||||
Ok(match &this.body {
|
Ok(match &this.body {
|
||||||
Some(body) => commands![
|
Some(body) => commands![
|
||||||
SetStyle(new_style),
|
SetStyle(style),
|
||||||
LayoutTree(body),
|
LayoutTree(body),
|
||||||
SetStyle(ctx.style.clone()),
|
SetStyle(ctx.style.clone()),
|
||||||
],
|
],
|
||||||
None => commands![SetStyle(new_style)]
|
None => commands![SetStyle(style)]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,5 +29,4 @@ Right Again: {lorem:10}
|
|||||||
[page.break]
|
[page.break]
|
||||||
|
|
||||||
// ---------------------------------- //
|
// ---------------------------------- //
|
||||||
// All in one line.
|
All in one line: {lorem:25} [align: right] {lorem:50} [align: left] {lorem:15}
|
||||||
All in one line: {lorem:25} [align: right][{lorem:50}] {lorem:15}
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{size:420pt x 300pt}
|
{size:420pt x 300pt}
|
||||||
|
|
||||||
[box: flow = horizontal][
|
[box][
|
||||||
*Technical University Berlin* [n]
|
*Technical University Berlin* [n]
|
||||||
*Faculty II, Institute for Mathematics* [n]
|
*Faculty II, Institute for Mathematics* [n]
|
||||||
Secretary Example [n]
|
Secretary Example [n]
|
||||||
Prof. Dr. Example [n]
|
Prof. Dr. Example [n]
|
||||||
Assistant #1, Assistant #2, Assistant #3
|
Assistant #1, Assistant #2, Assistant #3
|
||||||
|
|
||||||
[align: right][*WiSe 2019/2020* [n] Week 1]
|
|
||||||
]
|
]
|
||||||
|
[align: right][*WiSe 2019/2020* [n] Week 1]
|
||||||
|
|
||||||
[v: 3mm]
|
[v: 3mm]
|
||||||
|
|
||||||
[align: center][
|
[align: center][
|
||||||
@ -17,9 +17,7 @@
|
|||||||
*Alle Antworten sind zu beweisen.*
|
*Alle Antworten sind zu beweisen.*
|
||||||
]
|
]
|
||||||
|
|
||||||
[box: flow = horizontal][
|
|
||||||
*1. Aufgabe* [align: right][(1 + 1 + 2 Punkte)]
|
*1. Aufgabe* [align: right][(1 + 1 + 2 Punkte)]
|
||||||
]
|
|
||||||
|
|
||||||
Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
|
Ein _Binärbaum_ ist ein Wurzelbaum, in dem jeder Knoten ≤ 2 Kinder hat.
|
||||||
Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel
|
Die Tiefe eines Knotens _v_ ist die Länge des eindeutigen Weges von der Wurzel
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[align: center][{include:shakespeare.tpl}]
|
[align: center][{include:shakespeare.tpl}] [page.break]
|
||||||
[align: left][{include:shakespeare.tpl}]
|
[align: left][{include:shakespeare.tpl}] [page.break]
|
||||||
[align: right][{include:shakespeare.tpl}]
|
[align: right][{include:shakespeare.tpl}]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user