mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Axes updating for flex layouter 📐
This commit is contained in:
parent
1f009b5b95
commit
4d0bdc4ca4
@ -23,6 +23,11 @@ pub struct FlexLayouter {
|
|||||||
stack: StackLayouter,
|
stack: StackLayouter,
|
||||||
units: Vec<FlexUnit>,
|
units: Vec<FlexUnit>,
|
||||||
|
|
||||||
|
merged_actions: LayoutActionList,
|
||||||
|
merged_dimensions: Size2D,
|
||||||
|
max_left: Size,
|
||||||
|
max_right: Size,
|
||||||
|
|
||||||
usable: Size,
|
usable: Size,
|
||||||
run: FlexRun,
|
run: FlexRun,
|
||||||
space: Option<Size>,
|
space: Option<Size>,
|
||||||
@ -54,7 +59,7 @@ enum FlexUnit {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct FlexRun {
|
struct FlexRun {
|
||||||
content: Vec<(Size, Layout)>,
|
content: Vec<(Size, Size, Layout)>,
|
||||||
size: Size2D,
|
size: Size2D,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,12 +72,18 @@ impl FlexLayouter {
|
|||||||
shrink_to_fit: ctx.shrink_to_fit,
|
shrink_to_fit: ctx.shrink_to_fit,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let usable = stack.usable().x;
|
||||||
FlexLayouter {
|
FlexLayouter {
|
||||||
ctx,
|
ctx,
|
||||||
units: vec![],
|
units: vec![],
|
||||||
stack,
|
stack,
|
||||||
|
|
||||||
usable: stack.usable().x,
|
merged_actions: LayoutActionList::new(),
|
||||||
|
merged_dimensions: Size2D::with_x(usable),
|
||||||
|
max_left: Size::zero(),
|
||||||
|
max_right: usable,
|
||||||
|
|
||||||
|
usable,
|
||||||
run: FlexRun { content: vec![], size: Size2D::zero() },
|
run: FlexRun { content: vec![], size: Size2D::zero() },
|
||||||
space: None,
|
space: None,
|
||||||
}
|
}
|
||||||
@ -158,27 +169,6 @@ impl FlexLayouter {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish the current flex run.
|
|
||||||
fn finish_run(&mut self) -> LayoutResult<()> {
|
|
||||||
let mut actions = LayoutActionList::new();
|
|
||||||
for (x, layout) in self.run.content.drain(..) {
|
|
||||||
let position = self.ctx.axes.specialize(Size2D::with_x(x));
|
|
||||||
actions.add_layout(position, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.run.size.y += self.ctx.flex_spacing;
|
|
||||||
|
|
||||||
self.stack.add(Layout {
|
|
||||||
dimensions: self.ctx.axes.specialize(self.run.size),
|
|
||||||
actions: actions.into_vec(),
|
|
||||||
debug_render: false,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
self.run.size = Size2D::zero();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Layout a content box into the current flex run or start a new run if
|
/// Layout a content box into the current flex run or start a new run if
|
||||||
/// it does not fit.
|
/// it does not fit.
|
||||||
fn layout_box(&mut self, boxed: Layout) -> LayoutResult<()> {
|
fn layout_box(&mut self, boxed: Layout) -> LayoutResult<()> {
|
||||||
@ -204,7 +194,10 @@ impl FlexLayouter {
|
|||||||
|
|
||||||
self.layout_space();
|
self.layout_space();
|
||||||
|
|
||||||
self.run.content.push((self.run.size.x, boxed));
|
let offset = self.run.size.x;
|
||||||
|
let anchor = self.ctx.axes.primary.anchor(size.x);
|
||||||
|
self.run.content.push((offset, anchor, boxed));
|
||||||
|
|
||||||
self.run.size.x += size.x;
|
self.run.size.x += size.x;
|
||||||
self.run.size.y = crate::size::max(self.run.size.y, size.y);
|
self.run.size.y = crate::size::max(self.run.size.y, size.y);
|
||||||
|
|
||||||
@ -220,7 +213,54 @@ impl FlexLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn layout_set_axes(&mut self, axes: LayoutAxes) {
|
fn layout_set_axes(&mut self, axes: LayoutAxes) {
|
||||||
// TODO
|
if axes.primary != self.ctx.axes.primary {
|
||||||
|
self.finish_aligned_run();
|
||||||
|
self.usable = match axes.primary.alignment {
|
||||||
|
Alignment::Origin => self.max_right,
|
||||||
|
Alignment::Center => self.max_right - self.max_left,
|
||||||
|
Alignment::End => self.merged_dimensions.x - self.max_left,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if axes.secondary != self.ctx.axes.secondary {
|
||||||
|
self.stack.set_axes(axes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finish the current flex run.
|
||||||
|
fn finish_run(&mut self) -> LayoutResult<()> {
|
||||||
|
self.finish_aligned_run();
|
||||||
|
|
||||||
|
let actions = std::mem::replace(&mut self.merged_actions, LayoutActionList::new());
|
||||||
|
self.stack.add(Layout {
|
||||||
|
dimensions: self.ctx.axes.specialize(self.merged_dimensions),
|
||||||
|
actions: actions.into_vec(),
|
||||||
|
debug_render: false,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.merged_dimensions.y = Size::zero();
|
||||||
|
self.max_left = Size::zero();
|
||||||
|
self.max_right = self.merged_dimensions.x;
|
||||||
|
self.usable = self.merged_dimensions.x;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish_aligned_run(&mut self) -> LayoutResult<()> {
|
||||||
|
let anchor = self.ctx.axes.primary.anchor(self.merged_dimensions.x);
|
||||||
|
let factor = if self.ctx.axes.primary.axis.is_positive() { 1 } else { -1 };
|
||||||
|
|
||||||
|
for (offset, layout_anchor, layout) in self.run.content.drain(..) {
|
||||||
|
let general_position = Size2D::with_x(anchor - layout_anchor + factor * offset);
|
||||||
|
let position = self.ctx.axes.specialize(general_position);
|
||||||
|
|
||||||
|
self.merged_actions.add_layout(position, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.merged_dimensions.y = crate::size::max(self.merged_dimensions.y, self.run.size.y);
|
||||||
|
self.run.size = Size2D::zero();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This layouter's context.
|
/// This layouter's context.
|
||||||
|
@ -202,20 +202,20 @@ impl LayoutAxes {
|
|||||||
/// the layouting axes, that is:
|
/// the layouting axes, that is:
|
||||||
/// - The x coordinate describes the primary axis instead of the horizontal one.
|
/// - The x coordinate describes the primary axis instead of the horizontal one.
|
||||||
/// - The y coordinate describes the secondary axis instead of the vertical one.
|
/// - The y coordinate describes the secondary axis instead of the vertical one.
|
||||||
pub fn generalize(&self, space: Size2D) -> Size2D {
|
pub fn generalize(&self, size: Size2D) -> Size2D {
|
||||||
if self.primary.axis.is_horizontal() {
|
if self.primary.axis.is_horizontal() {
|
||||||
space
|
size
|
||||||
} else {
|
} else {
|
||||||
Size2D { x: space.y, y: space.x }
|
Size2D { x: size.y, y: size.x }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the specialized version of this generalized Size2D.
|
/// Returns the specialized version of this generalized Size2D.
|
||||||
/// (Inverse to `generalized`).
|
/// (Inverse to `generalized`).
|
||||||
pub fn specialize(&self, space: Size2D) -> Size2D {
|
pub fn specialize(&self, size: Size2D) -> Size2D {
|
||||||
// In fact, generalized is its own inverse. For reasons of clarity
|
// In fact, generalized is its own inverse. For reasons of clarity
|
||||||
// at the call site, we still have this second function.
|
// at the call site, we still have this second function.
|
||||||
self.generalize(space)
|
self.generalize(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The position of the anchor specified by the two aligned axes
|
/// The position of the anchor specified by the two aligned axes
|
||||||
|
@ -150,7 +150,7 @@ impl StackLayouter {
|
|||||||
let factor = if self.ctx.axes.secondary.axis.is_positive() { 1 } else { -1 };
|
let factor = if self.ctx.axes.secondary.axis.is_positive() { 1 } else { -1 };
|
||||||
|
|
||||||
for (offset, layout_anchor, layout) in self.boxes.drain(..) {
|
for (offset, layout_anchor, layout) in self.boxes.drain(..) {
|
||||||
let general_position = anchor - layout_anchor + Size2D::with_y(offset * factor);
|
let general_position = anchor - layout_anchor + Size2D::with_y(factor * offset);
|
||||||
let position = start + self.ctx.axes.specialize(general_position);
|
let position = start + self.ctx.axes.specialize(general_position);
|
||||||
|
|
||||||
self.merged_actions.add_layout(position, layout);
|
self.merged_actions.add_layout(position, layout);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user