From d1ecb7e52eb2ab7ac4fde89bdc1c615d92ae3c7b Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 28 Oct 2021 16:51:57 +0200 Subject: [PATCH] Add `move` function --- src/library/layout.rs | 44 +++++++++++++++++++++++++++++++++++++- src/library/mod.rs | 5 +++-- tests/ref/layout/move.png | Bin 0 -> 693 bytes tests/typ/layout/move.typ | 11 ++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/ref/layout/move.png create mode 100644 tests/typ/layout/move.typ diff --git a/src/library/layout.rs b/src/library/layout.rs index f7fb2882c..e5650664d 100644 --- a/src/library/layout.rs +++ b/src/library/layout.rs @@ -143,7 +143,7 @@ pub fn v(_: &mut EvalContext, args: &mut Args) -> TypResult { } /// `box`: Place content in a rectangular box. -pub fn boxed(_: &mut EvalContext, args: &mut Args) -> TypResult { +pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult { 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 { }))) } +/// `move`: Move content without affecting layout. +pub fn move_(_: &mut EvalContext, args: &mut Args) -> TypResult { + #[derive(Debug, Hash)] + struct MoveNode { + offset: Spec>, + 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 { enum Child { diff --git a/src/library/mod.rs b/src/library/mod.rs index ac2085eb9..6d3de11d5 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 0000000000000000000000000000000000000000..dc2e7ab3ef8ceaa3cd4fe2078c50df22ced49416 GIT binary patch literal 693 zcmeAS@N?(olHy`uVBq!ia0y~yU}OQZy*Ypc!)B>vw;33iYCK&WLn>~)y?!zGwt>L0 zkGBt0z1Y2{(a3?Zh&h$HoH@1mG}|k-Ghi&$s9exeFR#J0?ZFnlu4`&l@(Bkvv2cDD z?l*DO5$ishv@t?wn)Km%F=qo79H_-iFmB)0mJL?wLX1tqFPF#PHL0*)S!KVf@80$J z#*?xxzZfQW@G#zZck`4-Ltx)d5zBY}OH1mOB(u$NQION~TdO3gz>`^Bm&NTEdWxZA zm;Kh5J?DcLDIF;JxhixXB7TcL(kbqFX~o2os;9!wx_i4G$a&m{LiA2A+OBj(^0IGgE5nSft}JtO0<$w4cH9;?^v!Yl zo#{6pzH++E;$&5_@C@I4=M|6ZWEHQqCB)8hNtou>xKXJ`x~Z<^!IQs#|8Bi^HFbg6 zk>n?vIhJa$HmzX@JoH{*&WbG4%d88`STb|D6KiknThh$bbDrT}Nc!==^G;norvEnJ z+Mx})(@$^Xe>v-x^_sXRJFf1WGJV~@