mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Pad function 🔲
This commit is contained in:
parent
b0446cbdd1
commit
4e5f85aa4a
@ -80,6 +80,45 @@ impl<'a> ExecContext<'a> {
|
||||
self.inner.push(node);
|
||||
}
|
||||
|
||||
/// Push a normal word space.
|
||||
pub fn push_space(&mut self) {
|
||||
let em = self.state.font.font_size();
|
||||
self.push(NodeSpacing {
|
||||
amount: self.state.par.word_spacing.resolve(em),
|
||||
softness: Softness::Soft,
|
||||
});
|
||||
}
|
||||
|
||||
/// Push text into the context.
|
||||
///
|
||||
/// The text is split into lines at newlines.
|
||||
pub fn push_text(&mut self, text: &str) {
|
||||
let mut newline = false;
|
||||
for line in text.split_terminator(is_newline) {
|
||||
if newline {
|
||||
self.apply_linebreak();
|
||||
}
|
||||
|
||||
let node = self.make_text_node(line.into());
|
||||
self.push(node);
|
||||
newline = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute the body of a function and return the result as a stack node.
|
||||
pub fn exec_body(&mut self, body: &ValueTemplate, expand: Spec<Expansion>) -> Node {
|
||||
let dirs = self.state.dirs;
|
||||
let align = self.state.align;
|
||||
|
||||
self.start_group(ContentGroup);
|
||||
self.start_par_group();
|
||||
body.exec(self);
|
||||
self.end_par_group();
|
||||
let children = self.end_group::<ContentGroup>().1;
|
||||
|
||||
NodeStack { dirs, align, expand, children }.into()
|
||||
}
|
||||
|
||||
/// Start a page group based on the active page state.
|
||||
///
|
||||
/// The `softness` is a hint on whether empty pages should be kept in the
|
||||
@ -130,22 +169,6 @@ impl<'a> ExecContext<'a> {
|
||||
group.softness
|
||||
}
|
||||
|
||||
/// Start a content group.
|
||||
///
|
||||
/// This also starts an inner paragraph.
|
||||
pub fn start_content_group(&mut self) {
|
||||
self.start_group(ContentGroup);
|
||||
self.start_par_group();
|
||||
}
|
||||
|
||||
/// End a content group and return the resulting nodes.
|
||||
///
|
||||
/// This also ends an inner paragraph.
|
||||
pub fn end_content_group(&mut self) -> Vec<Node> {
|
||||
self.end_par_group();
|
||||
self.end_group::<ContentGroup>().1
|
||||
}
|
||||
|
||||
/// Start a paragraph group based on the active text state.
|
||||
pub fn start_par_group(&mut self) {
|
||||
let em = self.state.font.font_size();
|
||||
@ -218,29 +241,28 @@ impl<'a> ExecContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Push a normal word space.
|
||||
pub fn push_space(&mut self) {
|
||||
/// Set the font to monospace.
|
||||
pub fn apply_monospace(&mut self) {
|
||||
let families = self.state.font.families_mut();
|
||||
families.list.insert(0, "monospace".to_string());
|
||||
families.flatten();
|
||||
}
|
||||
|
||||
/// Apply a forced line break.
|
||||
pub fn apply_linebreak(&mut self) {
|
||||
self.end_par_group();
|
||||
self.start_par_group();
|
||||
}
|
||||
|
||||
/// Apply a forced paragraph break.
|
||||
pub fn apply_parbreak(&mut self) {
|
||||
self.end_par_group();
|
||||
let em = self.state.font.font_size();
|
||||
self.push(NodeSpacing {
|
||||
amount: self.state.par.word_spacing.resolve(em),
|
||||
amount: self.state.par.par_spacing.resolve(em),
|
||||
softness: Softness::Soft,
|
||||
});
|
||||
}
|
||||
|
||||
/// Push text into the context.
|
||||
///
|
||||
/// The text is split into lines at newlines.
|
||||
pub fn push_text(&mut self, text: &str) {
|
||||
let mut newline = false;
|
||||
for line in text.split_terminator(is_newline) {
|
||||
if newline {
|
||||
self.apply_linebreak();
|
||||
}
|
||||
|
||||
let node = self.make_text_node(line.into());
|
||||
self.push(node);
|
||||
newline = true;
|
||||
}
|
||||
self.start_par_group();
|
||||
}
|
||||
|
||||
/// Construct a text node from the given string based on the active text
|
||||
@ -269,30 +291,6 @@ impl<'a> ExecContext<'a> {
|
||||
variant,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the font to monospace.
|
||||
pub fn apply_monospace(&mut self) {
|
||||
let families = self.state.font.families_mut();
|
||||
families.list.insert(0, "monospace".to_string());
|
||||
families.flatten();
|
||||
}
|
||||
|
||||
/// Apply a forced line break.
|
||||
pub fn apply_linebreak(&mut self) {
|
||||
self.end_par_group();
|
||||
self.start_par_group();
|
||||
}
|
||||
|
||||
/// Apply a forced paragraph break.
|
||||
pub fn apply_parbreak(&mut self) {
|
||||
self.end_par_group();
|
||||
let em = self.state.font.font_size();
|
||||
self.push(NodeSpacing {
|
||||
amount: self.state.par.par_spacing.resolve(em),
|
||||
softness: Softness::Soft,
|
||||
});
|
||||
self.start_par_group();
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines how an item interacts with surrounding items.
|
||||
|
@ -7,6 +7,7 @@ mod align;
|
||||
mod base;
|
||||
mod font;
|
||||
mod image;
|
||||
mod pad;
|
||||
mod page;
|
||||
mod shapes;
|
||||
mod spacing;
|
||||
@ -15,6 +16,7 @@ pub use self::image::*;
|
||||
pub use align::*;
|
||||
pub use base::*;
|
||||
pub use font::*;
|
||||
pub use pad::*;
|
||||
pub use page::*;
|
||||
pub use shapes::*;
|
||||
pub use spacing::*;
|
||||
@ -46,6 +48,7 @@ pub fn new() -> Scope {
|
||||
set!(func: "font", font);
|
||||
set!(func: "h", h);
|
||||
set!(func: "image", image);
|
||||
set!(func: "pad", pad);
|
||||
set!(func: "page", page);
|
||||
set!(func: "pagebreak", pagebreak);
|
||||
set!(func: "repr", repr);
|
||||
|
38
src/library/pad.rs
Normal file
38
src/library/pad.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use super::*;
|
||||
|
||||
/// `pad`: Pad content at the sides.
|
||||
///
|
||||
/// # Positional arguments
|
||||
/// - Padding for all sides: `padding`, of type `linear` relative to sides.
|
||||
/// - Body: of type `template`.
|
||||
///
|
||||
/// # Named arguments
|
||||
/// - Left padding: `left`, of type `linear` relative to parent width.
|
||||
/// - Right padding: `right`, of type `linear` relative to parent width.
|
||||
/// - Top padding: `top`, of type `linear` relative to parent height.
|
||||
/// - Bottom padding: `bottom`, of type `linear` relative to parent height.
|
||||
pub fn pad(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
|
||||
let all = args.find(ctx);
|
||||
let left = args.get(ctx, "left");
|
||||
let top = args.get(ctx, "top");
|
||||
let right = args.get(ctx, "right");
|
||||
let bottom = args.get(ctx, "bottom");
|
||||
let body = args.require::<ValueTemplate>(ctx, "body").unwrap_or_default();
|
||||
|
||||
let padding = Sides::new(
|
||||
left.or(all).unwrap_or_default(),
|
||||
top.or(all).unwrap_or_default(),
|
||||
right.or(all).unwrap_or_default(),
|
||||
bottom.or(all).unwrap_or_default(),
|
||||
);
|
||||
|
||||
Value::template("pad", move |ctx| {
|
||||
let snapshot = ctx.state.clone();
|
||||
|
||||
let expand = Spec::uniform(Expansion::Fit);
|
||||
let child = ctx.exec_body(&body, expand);
|
||||
ctx.push(NodePad { padding, child });
|
||||
|
||||
ctx.state = snapshot;
|
||||
})
|
||||
}
|
@ -24,28 +24,18 @@ pub fn box_(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
|
||||
let main = args.get(ctx, "main-dir");
|
||||
let cross = args.get(ctx, "cross-dir");
|
||||
let color = args.get(ctx, "color");
|
||||
let body = args.find::<ValueTemplate>(ctx);
|
||||
let body = args.find::<ValueTemplate>(ctx).unwrap_or_default();
|
||||
|
||||
let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
|
||||
let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
|
||||
|
||||
Value::template("box", move |ctx| {
|
||||
let snapshot = ctx.state.clone();
|
||||
|
||||
ctx.set_dirs(Gen::new(main, cross));
|
||||
let dirs = ctx.state.dirs;
|
||||
let align = ctx.state.align;
|
||||
|
||||
ctx.start_content_group();
|
||||
if let Some(body) = &body {
|
||||
body.exec(ctx);
|
||||
}
|
||||
let children = ctx.end_content_group();
|
||||
|
||||
let fill_if = |c| if c { Expansion::Fill } else { Expansion::Fit };
|
||||
let expand = Spec::new(fill_if(width.is_some()), fill_if(height.is_some()));
|
||||
let fixed = NodeFixed {
|
||||
width,
|
||||
height,
|
||||
child: NodeStack { dirs, align, expand, children }.into(),
|
||||
};
|
||||
let child = ctx.exec_body(&body, expand);
|
||||
let fixed = NodeFixed { width, height, child };
|
||||
|
||||
if let Some(color) = color {
|
||||
ctx.push(NodeBackground {
|
||||
|
BIN
tests/ref/library/pad.png
Normal file
BIN
tests/ref/library/pad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 180 B |
3
tests/typ/library/pad.typ
Normal file
3
tests/typ/library/pad.typ
Normal file
@ -0,0 +1,3 @@
|
||||
#box(color: #9feb52)[
|
||||
#pad(10pt, box(color: #eb5278, width: 20pt, height: 20pt))
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user