mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Don't wrap already layoutable nodes into flows/pars unnecessarily
This commit is contained in:
parent
73c4701749
commit
79638d4bbd
@ -149,12 +149,15 @@ impl Template {
|
|||||||
Self(Rc::new(vec![TemplateNode::Decorated(deco, self)]))
|
Self(Rc::new(vec![TemplateNode::Decorated(deco, self)]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the flow node resulting from instantiating the template with the
|
/// Pack the template into a layout node.
|
||||||
/// given style.
|
pub fn pack(&self, style: &Style) -> PackedNode {
|
||||||
pub fn to_flow(&self, style: &Style) -> FlowNode {
|
if let [TemplateNode::Block(f) | TemplateNode::Inline(f)] = self.0.as_slice() {
|
||||||
let mut builder = Builder::new(style, false);
|
f(style)
|
||||||
builder.template(self);
|
} else {
|
||||||
builder.build_flow()
|
let mut builder = Builder::new(style, false);
|
||||||
|
builder.template(self);
|
||||||
|
builder.build_flow().pack()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the layout tree resulting from instantiating the template with the
|
/// Build the layout tree resulting from instantiating the template with the
|
||||||
|
@ -124,7 +124,7 @@ impl Walk for EnumNode {
|
|||||||
|
|
||||||
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
||||||
ctx.template += Template::from_block(move |style| {
|
ctx.template += Template::from_block(move |style| {
|
||||||
let label = ParNode {
|
let label = Layout::pack(ParNode {
|
||||||
dir: style.par.dir,
|
dir: style.par.dir,
|
||||||
leading: style.leading(),
|
leading: style.leading(),
|
||||||
children: vec![ParChild::Text(
|
children: vec![ParChild::Text(
|
||||||
@ -132,13 +132,13 @@ fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) {
|
|||||||
style.aligns.inline,
|
style.aligns.inline,
|
||||||
Rc::clone(&style.text),
|
Rc::clone(&style.text),
|
||||||
)],
|
)],
|
||||||
};
|
});
|
||||||
|
|
||||||
let spacing = style.text.size / 2.0;
|
let spacing = style.text.size / 2.0;
|
||||||
GridNode {
|
GridNode {
|
||||||
tracks: Spec::new(vec![TrackSizing::Auto; 2], vec![]),
|
tracks: Spec::new(vec![TrackSizing::Auto; 2], vec![]),
|
||||||
gutter: Spec::new(vec![TrackSizing::Linear(spacing.into())], vec![]),
|
gutter: Spec::new(vec![TrackSizing::Linear(spacing.into())], vec![]),
|
||||||
children: vec![label.pack(), body.to_flow(style).pack()],
|
children: vec![label, body.pack(style)],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ pub fn flow(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|child| match child {
|
.map(|child| match child {
|
||||||
Child::Spacing(spacing) => FlowChild::Spacing(*spacing),
|
Child::Spacing(spacing) => FlowChild::Spacing(*spacing),
|
||||||
Child::Any(child) => {
|
Child::Any(node) => FlowChild::Node(node.pack(style), style.aligns.block),
|
||||||
FlowChild::Node(child.to_flow(style).pack(), style.aligns.block)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
GridNode {
|
GridNode {
|
||||||
tracks: tracks.clone(),
|
tracks: tracks.clone(),
|
||||||
gutter: gutter.clone(),
|
gutter: gutter.clone(),
|
||||||
children: children.iter().map(|child| child.to_flow(style).pack()).collect(),
|
children: children.iter().map(|child| child.pack(style)).collect(),
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,7 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Ok(Value::Template(Template::from_inline(move |style| {
|
Ok(Value::Template(Template::from_inline(move |style| {
|
||||||
PadNode {
|
PadNode { padding, child: body.pack(style) }
|
||||||
padding,
|
|
||||||
child: body.to_flow(style).pack(),
|
|
||||||
}
|
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,21 +56,11 @@ pub fn circle(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
|
|
||||||
fn shape_impl(
|
fn shape_impl(
|
||||||
kind: ShapeKind,
|
kind: ShapeKind,
|
||||||
mut width: Option<Linear>,
|
width: Option<Linear>,
|
||||||
mut height: Option<Linear>,
|
height: Option<Linear>,
|
||||||
fill: Option<Color>,
|
fill: Option<Color>,
|
||||||
body: Option<Template>,
|
body: Option<Template>,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
// Set default shape size if there's no body.
|
|
||||||
if body.is_none() {
|
|
||||||
let v = Length::pt(30.0).into();
|
|
||||||
height.get_or_insert(v);
|
|
||||||
width.get_or_insert(match kind {
|
|
||||||
ShapeKind::Square | ShapeKind::Circle => v,
|
|
||||||
ShapeKind::Rect | ShapeKind::Ellipse => 1.5 * v,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set default fill if there's no fill.
|
// Set default fill if there's no fill.
|
||||||
let fill = fill.unwrap_or(Color::Rgba(RgbaColor::gray(175)));
|
let fill = fill.unwrap_or(Color::Rgba(RgbaColor::gray(175)));
|
||||||
|
|
||||||
@ -78,7 +68,7 @@ fn shape_impl(
|
|||||||
let shape = Layout::pack(ShapeNode {
|
let shape = Layout::pack(ShapeNode {
|
||||||
kind,
|
kind,
|
||||||
fill: Some(Paint::Color(fill)),
|
fill: Some(Paint::Color(fill)),
|
||||||
child: body.as_ref().map(|body| body.to_flow(style).pack()),
|
child: body.as_ref().map(|body| body.pack(style)),
|
||||||
});
|
});
|
||||||
|
|
||||||
if width.is_some() || height.is_some() {
|
if width.is_some() || height.is_some() {
|
||||||
@ -126,15 +116,15 @@ impl Layout for ShapeNode {
|
|||||||
let mut frame = if let Some(child) = &self.child {
|
let mut frame = if let Some(child) = &self.child {
|
||||||
let mut node: &dyn Layout = child;
|
let mut node: &dyn Layout = child;
|
||||||
|
|
||||||
let padded;
|
let storage;
|
||||||
if matches!(self.kind, ShapeKind::Circle | ShapeKind::Ellipse) {
|
if matches!(self.kind, ShapeKind::Circle | ShapeKind::Ellipse) {
|
||||||
// Padding with this ratio ensures that a rectangular child fits
|
// Padding with this ratio ensures that a rectangular child fits
|
||||||
// perfectly into a circle / an ellipse.
|
// perfectly into a circle / an ellipse.
|
||||||
padded = PadNode {
|
storage = PadNode {
|
||||||
padding: Sides::splat(Relative::new(0.5 - SQRT_2 / 4.0).into()),
|
padding: Sides::splat(Relative::new(0.5 - SQRT_2 / 4.0).into()),
|
||||||
child: child.clone(),
|
child: child.clone(),
|
||||||
};
|
};
|
||||||
node = &padded;
|
node = &storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, layout the child.
|
// Now, layout the child.
|
||||||
@ -155,7 +145,24 @@ impl Layout for ShapeNode {
|
|||||||
assert_eq!(frames.len(), 1);
|
assert_eq!(frames.len(), 1);
|
||||||
Rc::take(frames.into_iter().next().unwrap().item)
|
Rc::take(frames.into_iter().next().unwrap().item)
|
||||||
} else {
|
} else {
|
||||||
Frame::new(regions.current, regions.current.h)
|
let default = Length::pt(30.0);
|
||||||
|
let size = Size::new(
|
||||||
|
if regions.expand.x && regions.current.w.is_finite() {
|
||||||
|
regions.current.w
|
||||||
|
} else {
|
||||||
|
match self.kind {
|
||||||
|
ShapeKind::Square | ShapeKind::Circle => default,
|
||||||
|
ShapeKind::Rect | ShapeKind::Ellipse => 1.5 * default,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
if regions.expand.y && regions.current.h.is_finite() {
|
||||||
|
regions.current.h
|
||||||
|
} else {
|
||||||
|
default
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Frame::new(size, size.h)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add background shape if desired.
|
// Add background shape if desired.
|
||||||
|
@ -6,14 +6,11 @@ pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
let height = args.named("height")?;
|
let height = args.named("height")?;
|
||||||
let body: Template = args.find().unwrap_or_default();
|
let body: Template = args.find().unwrap_or_default();
|
||||||
Ok(Value::Template(Template::from_inline(move |style| {
|
Ok(Value::Template(Template::from_inline(move |style| {
|
||||||
let flow = body.to_flow(style).pack();
|
let child = body.pack(style);
|
||||||
if width.is_some() || height.is_some() {
|
if width.is_some() || height.is_some() {
|
||||||
Layout::pack(SizedNode {
|
Layout::pack(SizedNode { sizing: Spec::new(width, height), child })
|
||||||
sizing: Spec::new(width, height),
|
|
||||||
child: flow,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
flow
|
child
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -24,14 +21,11 @@ pub fn block(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
let height = args.named("height")?;
|
let height = args.named("height")?;
|
||||||
let body: Template = args.find().unwrap_or_default();
|
let body: Template = args.find().unwrap_or_default();
|
||||||
Ok(Value::Template(Template::from_block(move |style| {
|
Ok(Value::Template(Template::from_block(move |style| {
|
||||||
let flow = body.to_flow(style).pack();
|
let child = body.pack(style);
|
||||||
if width.is_some() || height.is_some() {
|
if width.is_some() || height.is_some() {
|
||||||
Layout::pack(SizedNode {
|
Layout::pack(SizedNode { sizing: Spec::new(width, height), child })
|
||||||
sizing: Spec::new(width, height),
|
|
||||||
child: flow,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
flow
|
child
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
children.push(StackChild::Spacing(v));
|
children.push(StackChild::Spacing(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = child.to_flow(style).pack();
|
let node = child.pack(style);
|
||||||
children.push(StackChild::Node(node));
|
children.push(StackChild::Node(node));
|
||||||
delayed = spacing;
|
delayed = spacing;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ pub fn move_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
|
|||||||
Ok(Value::Template(Template::from_inline(move |style| {
|
Ok(Value::Template(Template::from_inline(move |style| {
|
||||||
MoveNode {
|
MoveNode {
|
||||||
offset: Spec::new(x, y),
|
offset: Spec::new(x, y),
|
||||||
child: body.to_flow(style).pack(),
|
child: body.pack(style),
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
@ -14,16 +14,15 @@ Auto-sized circle. \
|
|||||||
]
|
]
|
||||||
|
|
||||||
Center-aligned rect in auto-sized circle.
|
Center-aligned rect in auto-sized circle.
|
||||||
#circle(fill: forest)[
|
|
||||||
#align(center, center)
|
|
||||||
#rect(fill: conifer, pad(5pt)[
|
|
||||||
But, soft!
|
|
||||||
])
|
|
||||||
]
|
|
||||||
|
|
||||||
100%-width rect in auto-sized circle. \
|
|
||||||
#circle(fill: forest,
|
#circle(fill: forest,
|
||||||
rect(width: 100%, fill: conifer)[
|
align(center, center,
|
||||||
|
rect(fill: conifer, pad(5pt)[But, soft!])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Rect in auto-sized circle. \
|
||||||
|
#circle(fill: forest,
|
||||||
|
rect(fill: conifer)[
|
||||||
But, soft! what light through yonder window breaks?
|
But, soft! what light through yonder window breaks?
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
#ellipse()
|
#ellipse()
|
||||||
|
|
||||||
---
|
---
|
||||||
100% rect in 100% ellipse in fixed rect. \
|
Rect in ellipse in fixed rect. \
|
||||||
#rect(width: 3cm, height: 2cm, fill: rgb("2a631a"),
|
#rect(width: 3cm, height: 2cm, fill: rgb("2a631a"),
|
||||||
ellipse(width: 100%, height: 100%, fill: forest,
|
ellipse(fill: forest,
|
||||||
rect(width: 100%, height: 100%, fill: conifer)[
|
rect(fill: conifer)[
|
||||||
#align(center, center)
|
#align(center, center)
|
||||||
Stuff inside an ellipse!
|
Stuff inside an ellipse!
|
||||||
]
|
]
|
||||||
|
@ -7,17 +7,17 @@
|
|||||||
#grid(
|
#grid(
|
||||||
columns: (auto, 1fr, 3fr, 0.25cm, 3%, 2mm + 10%),
|
columns: (auto, 1fr, 3fr, 0.25cm, 3%, 2mm + 10%),
|
||||||
cell(0.5cm, rgb("2a631a")),
|
cell(0.5cm, rgb("2a631a")),
|
||||||
cell(100%, forest),
|
cell(100%, forest),
|
||||||
cell(100%, conifer),
|
cell(100%, conifer),
|
||||||
cell(100%, rgb("ff0000")),
|
cell(100%, rgb("ff0000")),
|
||||||
cell(100%, rgb("00ff00")),
|
cell(100%, rgb("00ff00")),
|
||||||
cell(80%, rgb("00faf0")),
|
cell(80%, rgb("00faf0")),
|
||||||
cell(1cm, rgb("00ff00")),
|
cell(1cm, rgb("00ff00")),
|
||||||
cell(0.5cm, rgb("2a631a")),
|
cell(0.5cm, rgb("2a631a")),
|
||||||
cell(100%, forest),
|
cell(100%, forest),
|
||||||
cell(100%, conifer),
|
cell(100%, conifer),
|
||||||
cell(100%, rgb("ff0000")),
|
cell(100%, rgb("ff0000")),
|
||||||
cell(100%, rgb("00ff00")),
|
cell(100%, rgb("00ff00")),
|
||||||
)
|
)
|
||||||
|
|
||||||
#grid()
|
#grid()
|
||||||
@ -29,7 +29,7 @@
|
|||||||
row-gutter: 1fr,
|
row-gutter: 1fr,
|
||||||
rect(fill: eastern)[dddaa aaa aaa],
|
rect(fill: eastern)[dddaa aaa aaa],
|
||||||
rect(fill: conifer)[ccc],
|
rect(fill: conifer)[ccc],
|
||||||
rect(width: 100%, fill: rgb("dddddd"))[aaa],
|
rect(fill: rgb("dddddd"))[aaa],
|
||||||
)
|
)
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -39,6 +39,6 @@
|
|||||||
columns: (1fr,),
|
columns: (1fr,),
|
||||||
rows: (1fr, auto, 2fr),
|
rows: (1fr, auto, 2fr),
|
||||||
[],
|
[],
|
||||||
box(width: 100%)[A bit more to the top],
|
[A bit more to the top],
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
@ -67,9 +67,9 @@
|
|||||||
columns: 2 * (1fr,),
|
columns: 2 * (1fr,),
|
||||||
rows: (1fr, 2fr, auto, 1fr, 1cm),
|
rows: (1fr, 2fr, auto, 1fr, 1cm),
|
||||||
row-gutter: 10pt,
|
row-gutter: 10pt,
|
||||||
rect(height: 100%, width: 100%, fill: rgb("ff0000"))[No height],
|
rect(fill: rgb("ff0000"))[No height],
|
||||||
[foo],
|
[foo],
|
||||||
rect(height: 100%, width: 100%, fill: rgb("fc0030"))[Still no height],
|
rect(fill: rgb("fc0030"))[Still no height],
|
||||||
[bar],
|
[bar],
|
||||||
[The nature of being itself is in question. Am I One? What is being alive?],
|
[The nature of being itself is in question. Am I One? What is being alive?],
|
||||||
[baz],
|
[baz],
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
#grid(
|
#grid(
|
||||||
columns: (1fr,) * 4,
|
columns: (1fr,) * 4,
|
||||||
rows: (1cm,),
|
rows: (1cm,),
|
||||||
rect(width: 50%, height: 100%, fill: conifer),
|
rect(width: 50%, fill: conifer),
|
||||||
rect(width: 50%, height: 100%, fill: forest),
|
rect(width: 50%, fill: forest),
|
||||||
rect(width: 50%, height: 100%, fill: conifer),
|
rect(width: 50%, fill: conifer),
|
||||||
rect(width: 50%, height: 100%, fill: forest),
|
rect(width: 50%, fill: forest),
|
||||||
)
|
)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -13,9 +13,8 @@
|
|||||||
w => rect(width: w, height: 10pt, fill: next())
|
w => rect(width: w, height: 10pt, fill: next())
|
||||||
}
|
}
|
||||||
|
|
||||||
#let items = for w in widths { (shaded(w),) }
|
#let items = for w in widths { (align(right, shaded(w)),) }
|
||||||
|
|
||||||
#align(right)
|
|
||||||
#page(width: 50pt, margins: 0pt)
|
#page(width: 50pt, margins: 0pt)
|
||||||
#stack(dir: btt, ..items)
|
#stack(dir: btt, ..items)
|
||||||
#pagebreak()
|
#pagebreak()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user