summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-10-28 16:51:57 +0200
committerLaurenz <laurmaedje@gmail.com>2021-10-28 16:51:57 +0200
commitd1ecb7e52eb2ab7ac4fde89bdc1c615d92ae3c7b (patch)
treeab1d61bd5b3cc197a51cfe210cd1949a1fdba029
parent5c534fb42881b508175dd25129f62e604bdae403 (diff)
Add `move` function
-rw-r--r--src/library/layout.rs44
-rw-r--r--src/library/mod.rs5
-rw-r--r--tests/ref/layout/move.pngbin0 -> 693 bytes
-rw-r--r--tests/typ/layout/move.typ11
4 files changed, 57 insertions, 3 deletions
diff --git a/src/library/layout.rs b/src/library/layout.rs
index f7fb2882..e5650664 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -143,7 +143,7 @@ pub fn v(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
}
/// `box`: Place content in a rectangular box.
-pub fn boxed(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
+pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let width = args.named("width")?;
let height = args.named("height")?;
let fill = args.named("fill")?;
@@ -191,6 +191,48 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
})))
}
+/// `move`: Move content without affecting layout.
+pub fn move_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
+ #[derive(Debug, Hash)]
+ struct MoveNode {
+ offset: Spec<Option<Linear>>,
+ child: ShapeNode,
+ }
+
+ impl InlineLevel for MoveNode {
+ fn layout(&self, ctx: &mut LayoutContext, space: Length, base: Size) -> Frame {
+ let offset = Point::new(
+ self.offset.x.map(|x| x.resolve(base.w)).unwrap_or_default(),
+ self.offset.y.map(|y| y.resolve(base.h)).unwrap_or_default(),
+ );
+
+ let mut frame = self.child.layout(ctx, space, base);
+ for (point, _) in &mut frame.children {
+ *point += offset;
+ }
+
+ frame
+ }
+ }
+
+ let x = args.named("x")?;
+ let y = args.named("y")?;
+ let body: Template = args.expect("body")?;
+
+ Ok(Value::Template(Template::from_inline(move |style| {
+ MoveNode {
+ offset: Spec::new(x, y),
+ child: ShapeNode {
+ shape: ShapeKind::Rect,
+ width: None,
+ height: None,
+ fill: None,
+ child: Some(body.to_stack(style).pack()),
+ },
+ }
+ })))
+}
+
/// `stack`: Stack children along an axis.
pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
enum Child {
diff --git a/src/library/mod.rs b/src/library/mod.rs
index ac2085eb..6d3de11d 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -20,7 +20,7 @@ use crate::diag::{At, TypResult};
use crate::eval::{Args, Array, EvalContext, Scope, Str, Template, Value};
use crate::font::{FontFamily, FontStretch, FontStyle, FontWeight, VerticalFontMetric};
use crate::geom::*;
-use crate::layout::{BlockLevel, Spacing};
+use crate::layout::{BlockLevel, Frame, InlineLevel, LayoutContext, Spacing};
use crate::style::Style;
use crate::syntax::{Span, Spanned};
@@ -43,9 +43,10 @@ pub fn new() -> Scope {
std.def_func("h", h);
std.def_func("v", v);
std.def_func("align", align);
- std.def_func("box", boxed);
+ std.def_func("box", box_);
std.def_func("block", block);
std.def_func("pad", pad);
+ std.def_func("move", move_);
std.def_func("stack", stack);
std.def_func("grid", grid);
diff --git a/tests/ref/layout/move.png b/tests/ref/layout/move.png
new file mode 100644
index 00000000..dc2e7ab3
--- /dev/null
+++ b/tests/ref/layout/move.png
Binary files differ
diff --git a/tests/typ/layout/move.typ b/tests/typ/layout/move.typ
new file mode 100644
index 00000000..c1f97e15
--- /dev/null
+++ b/tests/typ/layout/move.typ
@@ -0,0 +1,11 @@
+#let size = 11pt
+#let tex = [{
+ [T]
+ h(-0.14 * size)
+ move(y: 0.22 * size)[E]
+ h(-0.12 * size)
+ [X]
+}]
+
+#font("Latin Modern Math", size)
+Not #tex!