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);
|
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.
|
/// Start a page group based on the active page state.
|
||||||
///
|
///
|
||||||
/// The `softness` is a hint on whether empty pages should be kept in the
|
/// The `softness` is a hint on whether empty pages should be kept in the
|
||||||
@ -130,22 +169,6 @@ impl<'a> ExecContext<'a> {
|
|||||||
group.softness
|
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.
|
/// Start a paragraph group based on the active text state.
|
||||||
pub fn start_par_group(&mut self) {
|
pub fn start_par_group(&mut self) {
|
||||||
let em = self.state.font.font_size();
|
let em = self.state.font.font_size();
|
||||||
@ -218,29 +241,28 @@ impl<'a> ExecContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a normal word space.
|
/// Set the font to monospace.
|
||||||
pub fn push_space(&mut self) {
|
pub fn apply_monospace(&mut self) {
|
||||||
let em = self.state.font.font_size();
|
let families = self.state.font.families_mut();
|
||||||
self.push(NodeSpacing {
|
families.list.insert(0, "monospace".to_string());
|
||||||
amount: self.state.par.word_spacing.resolve(em),
|
families.flatten();
|
||||||
softness: Softness::Soft,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push text into the context.
|
/// Apply a forced line break.
|
||||||
///
|
pub fn apply_linebreak(&mut self) {
|
||||||
/// The text is split into lines at newlines.
|
self.end_par_group();
|
||||||
pub fn push_text(&mut self, text: &str) {
|
self.start_par_group();
|
||||||
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());
|
/// Apply a forced paragraph break.
|
||||||
self.push(node);
|
pub fn apply_parbreak(&mut self) {
|
||||||
newline = true;
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a text node from the given string based on the active text
|
/// Construct a text node from the given string based on the active text
|
||||||
@ -269,30 +291,6 @@ impl<'a> ExecContext<'a> {
|
|||||||
variant,
|
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.
|
/// Defines how an item interacts with surrounding items.
|
||||||
|
@ -7,6 +7,7 @@ mod align;
|
|||||||
mod base;
|
mod base;
|
||||||
mod font;
|
mod font;
|
||||||
mod image;
|
mod image;
|
||||||
|
mod pad;
|
||||||
mod page;
|
mod page;
|
||||||
mod shapes;
|
mod shapes;
|
||||||
mod spacing;
|
mod spacing;
|
||||||
@ -15,6 +16,7 @@ pub use self::image::*;
|
|||||||
pub use align::*;
|
pub use align::*;
|
||||||
pub use base::*;
|
pub use base::*;
|
||||||
pub use font::*;
|
pub use font::*;
|
||||||
|
pub use pad::*;
|
||||||
pub use page::*;
|
pub use page::*;
|
||||||
pub use shapes::*;
|
pub use shapes::*;
|
||||||
pub use spacing::*;
|
pub use spacing::*;
|
||||||
@ -46,6 +48,7 @@ pub fn new() -> Scope {
|
|||||||
set!(func: "font", font);
|
set!(func: "font", font);
|
||||||
set!(func: "h", h);
|
set!(func: "h", h);
|
||||||
set!(func: "image", image);
|
set!(func: "image", image);
|
||||||
|
set!(func: "pad", pad);
|
||||||
set!(func: "page", page);
|
set!(func: "page", page);
|
||||||
set!(func: "pagebreak", pagebreak);
|
set!(func: "pagebreak", pagebreak);
|
||||||
set!(func: "repr", repr);
|
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 main = args.get(ctx, "main-dir");
|
||||||
let cross = args.get(ctx, "cross-dir");
|
let cross = args.get(ctx, "cross-dir");
|
||||||
let color = args.get(ctx, "color");
|
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| {
|
Value::template("box", move |ctx| {
|
||||||
let snapshot = ctx.state.clone();
|
let snapshot = ctx.state.clone();
|
||||||
|
|
||||||
ctx.set_dirs(Gen::new(main, cross));
|
ctx.set_dirs(Gen::new(main, cross));
|
||||||
let dirs = ctx.state.dirs;
|
|
||||||
let align = ctx.state.align;
|
|
||||||
|
|
||||||
ctx.start_content_group();
|
let child = ctx.exec_body(&body, expand);
|
||||||
if let Some(body) = &body {
|
let fixed = NodeFixed { width, height, child };
|
||||||
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(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(color) = color {
|
if let Some(color) = color {
|
||||||
ctx.push(NodeBackground {
|
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