mirror of
https://github.com/typst/typst
synced 2025-05-21 20:45:27 +08:00
Less vecs in layouting ⚡
This commit is contained in:
parent
38157b0e0c
commit
5243878d81
@ -34,6 +34,6 @@ impl Pages {
|
|||||||
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
|
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<BoxLayout> {
|
||||||
let areas = Areas::repeat(self.size);
|
let areas = Areas::repeat(self.size);
|
||||||
let layouted = self.child.layout(ctx, &areas);
|
let layouted = self.child.layout(ctx, &areas);
|
||||||
layouted.into_iter().filter_map(Layouted::into_boxed).collect()
|
layouted.into_boxes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub struct Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Fixed {
|
impl Layout for Fixed {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
|
||||||
let Area { rem, full } = areas.current;
|
let Area { rem, full } = areas.current;
|
||||||
let size = Size::new(
|
let size = Size::new(
|
||||||
self.width.map(|w| w.eval(full.width)).unwrap_or(rem.width),
|
self.width.map(|w| w.eval(full.width)).unwrap_or(rem.width),
|
||||||
|
@ -38,7 +38,7 @@ pub struct LayoutContext {
|
|||||||
/// Layout a node.
|
/// Layout a node.
|
||||||
pub trait Layout {
|
pub trait Layout {
|
||||||
/// Layout the node in the given layout context.
|
/// Layout the node in the given layout context.
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted>;
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sequence of areas to layout into.
|
/// A sequence of areas to layout into.
|
||||||
@ -129,14 +129,17 @@ pub enum Layouted {
|
|||||||
Spacing(Length),
|
Spacing(Length),
|
||||||
/// A box that should be added to and aligned in the parent.
|
/// A box that should be added to and aligned in the parent.
|
||||||
Boxed(BoxLayout, Gen<Align>),
|
Boxed(BoxLayout, Gen<Align>),
|
||||||
|
/// Multiple boxes.
|
||||||
|
Boxes(Vec<(BoxLayout, Gen<Align>)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layouted {
|
impl Layouted {
|
||||||
/// Return the box if this if its a box variant.
|
/// Return the box if this if its a box variant.
|
||||||
pub fn into_boxed(self) -> Option<BoxLayout> {
|
pub fn into_boxes(self) -> Vec<BoxLayout> {
|
||||||
match self {
|
match self {
|
||||||
Self::Spacing(_) => None,
|
Self::Spacing(_) => vec![],
|
||||||
Self::Boxed(boxed, _) => Some(boxed),
|
Self::Boxed(boxed, _) => vec![boxed],
|
||||||
|
Self::Boxes(boxes) => boxes.into_iter().map(|p| p.0).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ impl LayoutNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for LayoutNode {
|
impl Layout for LayoutNode {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
|
||||||
match self {
|
match self {
|
||||||
Self::Spacing(spacing) => spacing.layout(ctx, areas),
|
Self::Spacing(spacing) => spacing.layout(ctx, areas),
|
||||||
Self::Text(text) => text.layout(ctx, areas),
|
Self::Text(text) => text.layout(ctx, areas),
|
||||||
|
@ -11,27 +11,16 @@ pub struct Pad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Pad {
|
impl Layout for Pad {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
|
||||||
let shrink = |size| size - self.padding.eval(size).size();
|
let areas = shrink_areas(areas, self.padding);
|
||||||
let areas = Areas {
|
|
||||||
current: Area {
|
|
||||||
rem: shrink(areas.current.rem),
|
|
||||||
full: shrink(areas.current.full),
|
|
||||||
},
|
|
||||||
backlog: areas.backlog.iter().copied().map(shrink).collect(),
|
|
||||||
last: areas.last.map(shrink),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut layouted = self.child.layout(ctx, &areas);
|
let mut layouted = self.child.layout(ctx, &areas);
|
||||||
|
match &mut layouted {
|
||||||
for item in &mut layouted {
|
Layouted::Spacing(_) => {}
|
||||||
if let Layouted::Boxed(boxed, _) = item {
|
Layouted::Boxed(boxed, _) => pad_box(boxed, self.padding),
|
||||||
let padding = self.padding.eval(boxed.size);
|
Layouted::Boxes(boxes) => {
|
||||||
let origin = Point::new(padding.left, padding.top);
|
for (boxed, _) in boxes {
|
||||||
|
pad_box(boxed, self.padding);
|
||||||
boxed.size += padding.size();
|
|
||||||
for (point, _) in &mut boxed.elements {
|
|
||||||
*point += origin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,6 +29,30 @@ impl Layout for Pad {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shrink all areas by the padding.
|
||||||
|
fn shrink_areas(areas: &Areas, padding: Sides<Linear>) -> Areas {
|
||||||
|
let shrink = |size| size - padding.eval(size).size();
|
||||||
|
Areas {
|
||||||
|
current: Area {
|
||||||
|
rem: shrink(areas.current.rem),
|
||||||
|
full: shrink(areas.current.full),
|
||||||
|
},
|
||||||
|
backlog: areas.backlog.iter().copied().map(shrink).collect(),
|
||||||
|
last: areas.last.map(shrink),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enlarge the box and move all elements inwards.
|
||||||
|
fn pad_box(boxed: &mut BoxLayout, padding: Sides<Linear>) {
|
||||||
|
let padding = padding.eval(boxed.size);
|
||||||
|
let origin = Point::new(padding.left, padding.top);
|
||||||
|
|
||||||
|
boxed.size += padding.size();
|
||||||
|
for (point, _) in &mut boxed.elements {
|
||||||
|
*point += origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Pad> for LayoutNode {
|
impl From<Pad> for LayoutNode {
|
||||||
fn from(pad: Pad) -> Self {
|
fn from(pad: Pad) -> Self {
|
||||||
Self::dynamic(pad)
|
Self::dynamic(pad)
|
||||||
|
@ -19,17 +19,20 @@ pub struct Par {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Par {
|
impl Layout for Par {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
|
||||||
let mut layouter = ParLayouter::new(self, areas.clone());
|
let mut layouter = ParLayouter::new(self, areas.clone());
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
for layouted in child.layout(ctx, &layouter.areas) {
|
match child.layout(ctx, &layouter.areas) {
|
||||||
match layouted {
|
Layouted::Spacing(spacing) => layouter.spacing(spacing),
|
||||||
Layouted::Spacing(spacing) => layouter.spacing(spacing),
|
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns.cross),
|
||||||
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns.cross),
|
Layouted::Boxes(boxes) => {
|
||||||
|
for (boxed, aligns) in boxes {
|
||||||
|
layouter.boxed(boxed, aligns.cross);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layouter.finish()
|
Layouted::Boxes(layouter.finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +48,7 @@ struct ParLayouter<'a> {
|
|||||||
cross: SpecAxis,
|
cross: SpecAxis,
|
||||||
dirs: Gen<Dir>,
|
dirs: Gen<Dir>,
|
||||||
areas: Areas,
|
areas: Areas,
|
||||||
layouted: Vec<Layouted>,
|
layouted: Vec<(BoxLayout, Gen<Align>)>,
|
||||||
lines: Vec<(Length, BoxLayout, Align)>,
|
lines: Vec<(Length, BoxLayout, Align)>,
|
||||||
lines_size: Gen<Length>,
|
lines_size: Gen<Length>,
|
||||||
run: Vec<(Length, BoxLayout, Align)>,
|
run: Vec<(Length, BoxLayout, Align)>,
|
||||||
@ -169,13 +172,13 @@ impl<'a> ParLayouter<'a> {
|
|||||||
output.push_layout(pos, run);
|
output.push_layout(pos, run);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.layouted.push(Layouted::Boxed(output, self.par.aligns));
|
self.layouted.push((output, self.par.aligns));
|
||||||
|
|
||||||
self.areas.next();
|
self.areas.next();
|
||||||
self.lines_size = Gen::ZERO;
|
self.lines_size = Gen::ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(mut self) -> Vec<Layouted> {
|
fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
|
||||||
self.finish_run();
|
self.finish_run();
|
||||||
self.finish_area();
|
self.finish_area();
|
||||||
self.layouted
|
self.layouted
|
||||||
|
@ -15,8 +15,8 @@ pub struct Spacing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Spacing {
|
impl Layout for Spacing {
|
||||||
fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Vec<Layouted> {
|
fn layout(&self, _: &mut LayoutContext, _: &Areas) -> Layouted {
|
||||||
vec![Layouted::Spacing(self.amount)]
|
Layouted::Spacing(self.amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,17 +17,20 @@ pub struct Stack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Stack {
|
impl Layout for Stack {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted {
|
||||||
let mut layouter = StackLayouter::new(self, areas.clone());
|
let mut layouter = StackLayouter::new(self, areas.clone());
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
for layouted in child.layout(ctx, &layouter.areas) {
|
match child.layout(ctx, &layouter.areas) {
|
||||||
match layouted {
|
Layouted::Spacing(spacing) => layouter.spacing(spacing),
|
||||||
Layouted::Spacing(spacing) => layouter.spacing(spacing),
|
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns),
|
||||||
Layouted::Boxed(boxed, aligns) => layouter.boxed(boxed, aligns),
|
Layouted::Boxes(boxes) => {
|
||||||
|
for (boxed, aligns) in boxes {
|
||||||
|
layouter.boxed(boxed, aligns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layouter.finish()
|
Layouted::Boxes(layouter.finish())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +45,7 @@ struct StackLayouter<'a> {
|
|||||||
main: SpecAxis,
|
main: SpecAxis,
|
||||||
dirs: Gen<Dir>,
|
dirs: Gen<Dir>,
|
||||||
areas: Areas,
|
areas: Areas,
|
||||||
layouted: Vec<Layouted>,
|
layouted: Vec<(BoxLayout, Gen<Align>)>,
|
||||||
boxes: Vec<(Length, BoxLayout, Gen<Align>)>,
|
boxes: Vec<(Length, BoxLayout, Gen<Align>)>,
|
||||||
used: Gen<Length>,
|
used: Gen<Length>,
|
||||||
ruler: Align,
|
ruler: Align,
|
||||||
@ -134,14 +137,14 @@ impl<'a> StackLayouter<'a> {
|
|||||||
output.push_layout(pos, layout);
|
output.push_layout(pos, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.layouted.push(Layouted::Boxed(output, self.stack.aligns));
|
self.layouted.push((output, self.stack.aligns));
|
||||||
|
|
||||||
self.areas.next();
|
self.areas.next();
|
||||||
self.used = Gen::ZERO;
|
self.used = Gen::ZERO;
|
||||||
self.ruler = Align::Start;
|
self.ruler = Align::Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(mut self) -> Vec<Layouted> {
|
fn finish(mut self) -> Vec<(BoxLayout, Gen<Align>)> {
|
||||||
self.finish_area();
|
self.finish_area();
|
||||||
self.layouted
|
self.layouted
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ pub struct Text {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Layout for Text {
|
impl Layout for Text {
|
||||||
fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Vec<Layouted> {
|
fn layout(&self, ctx: &mut LayoutContext, _: &Areas) -> Layouted {
|
||||||
let mut loader = ctx.loader.borrow_mut();
|
let mut loader = ctx.loader.borrow_mut();
|
||||||
vec![Layouted::Boxed(
|
Layouted::Boxed(
|
||||||
shaping::shape(
|
shaping::shape(
|
||||||
&mut loader,
|
&mut loader,
|
||||||
&self.text,
|
&self.text,
|
||||||
@ -36,7 +36,7 @@ impl Layout for Text {
|
|||||||
self.variant,
|
self.variant,
|
||||||
),
|
),
|
||||||
self.aligns,
|
self.aligns,
|
||||||
)]
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user