From a9869c212f7c1bc77a52e301ad014641b014e834 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 26 May 2022 13:49:44 +0200 Subject: Locatable groups --- src/library/layout/grid.rs | 4 ++++ src/library/layout/locate.rs | 14 ++++++++++++++ src/library/layout/mod.rs | 2 ++ src/library/mod.rs | 3 ++- src/library/prelude.rs | 4 ++-- src/library/text/par.rs | 22 ++++++++++++---------- src/library/utility/locate.rs | 8 -------- src/library/utility/mod.rs | 2 -- 8 files changed, 36 insertions(+), 23 deletions(-) create mode 100644 src/library/layout/locate.rs delete mode 100644 src/library/utility/locate.rs (limited to 'src/library') diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs index 5b621732..4cad9de6 100644 --- a/src/library/layout/grid.rs +++ b/src/library/layout/grid.rs @@ -204,7 +204,9 @@ impl<'a> GridLayouter<'a> { /// Determines the columns sizes and then layouts the grid row-by-row. pub fn layout(mut self) -> TypResult>> { + self.ctx.pins.freeze(); self.measure_columns()?; + self.ctx.pins.unfreeze(); for y in 0 .. self.rows.len() { // Skip to next region if current one is full, but only for content @@ -370,10 +372,12 @@ impl<'a> GridLayouter<'a> { pod.base.x = self.regions.base.x; } + self.ctx.pins.freeze(); let mut sizes = node .layout(self.ctx, &pod, self.styles)? .into_iter() .map(|frame| frame.size.y); + self.ctx.pins.unfreeze(); // For each region, we want to know the maximum height any // column requires. diff --git a/src/library/layout/locate.rs b/src/library/layout/locate.rs new file mode 100644 index 00000000..e94a48ba --- /dev/null +++ b/src/library/layout/locate.rs @@ -0,0 +1,14 @@ +use crate::library::prelude::*; +use crate::model::{Group, LocateNode}; + +/// Format content with access to its location on the page. +pub fn locate(_: &mut Machine, args: &mut Args) -> TypResult { + let node = LocateNode::new(args.expect("recipe")?); + Ok(Value::Content(Content::Locate(node))) +} + +/// Create a new group of locatable elements. +pub fn group(_: &mut Machine, args: &mut Args) -> TypResult { + let key = args.expect("key")?; + Ok(Value::dynamic(Group::new(key))) +} diff --git a/src/library/layout/mod.rs b/src/library/layout/mod.rs index 588b15aa..6cf5b550 100644 --- a/src/library/layout/mod.rs +++ b/src/library/layout/mod.rs @@ -5,6 +5,7 @@ mod columns; mod container; mod flow; mod grid; +mod locate; mod pad; mod page; mod place; @@ -16,6 +17,7 @@ pub use columns::*; pub use container::*; pub use flow::*; pub use grid::*; +pub use locate::*; pub use pad::*; pub use page::*; pub use place::*; diff --git a/src/library/mod.rs b/src/library/mod.rs index 3321a36b..cf5d6e64 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -54,6 +54,8 @@ pub fn new() -> Scope { std.def_node::("columns"); std.def_node::("colbreak"); std.def_node::("place"); + std.def_fn("locate", layout::locate); + std.def_fn("group", layout::group); // Graphics. std.def_node::("image"); @@ -92,7 +94,6 @@ pub fn new() -> Scope { std.def_fn("roman", utility::roman); std.def_fn("symbol", utility::symbol); std.def_fn("lorem", utility::lorem); - std.def_fn("locate", utility::locate); // Predefined colors. std.def_const("black", Color::BLACK); diff --git a/src/library/prelude.rs b/src/library/prelude.rs index 371d6776..a61157a7 100644 --- a/src/library/prelude.rs +++ b/src/library/prelude.rs @@ -9,8 +9,8 @@ pub use typst_macros::node; pub use crate::diag::{with_alternative, At, Error, StrResult, TypError, TypResult}; pub use crate::eval::{ - Arg, Args, Array, Cast, Dict, Func, Machine, Node, RawAlign, RawLength, RawStroke, - Scope, Smart, Value, + Arg, Args, Array, Cast, Dict, Dynamic, Func, Machine, Node, RawAlign, RawLength, + RawStroke, Scope, Smart, Value, }; pub use crate::frame::*; pub use crate::geom::*; diff --git a/src/library/text/par.rs b/src/library/text/par.rs index 65098b61..709dc756 100644 --- a/src/library/text/par.rs +++ b/src/library/text/par.rs @@ -194,10 +194,11 @@ impl LinebreakNode { /// Range of a substring of text. type Range = std::ops::Range; -// The characters by which spacing and nodes are replaced in the paragraph's -// full text. -const SPACING_REPLACE: char = ' '; -const NODE_REPLACE: char = '\u{FFFC}'; +// The characters by which spacing, nodes and pins are replaced in the +// paragraph's full text. +const SPACING_REPLACE: char = ' '; // Space +const NODE_REPLACE: char = '\u{FFFC}'; // Object Replacement Character +const PIN_REPLACE: char = '\u{200D}'; // Zero Width Joiner /// A paragraph representation in which children are already layouted and text /// is already preshaped. @@ -287,8 +288,9 @@ impl Segment<'_> { fn len(&self) -> usize { match *self { Self::Text(len) => len, - Self::Spacing(_) | Self::Pin(_) => SPACING_REPLACE.len_utf8(), + Self::Spacing(_) => SPACING_REPLACE.len_utf8(), Self::Node(_) => NODE_REPLACE.len_utf8(), + Self::Pin(_) => PIN_REPLACE.len_utf8(), } } } @@ -323,10 +325,9 @@ impl<'a> Item<'a> { fn len(&self) -> usize { match self { Self::Text(shaped) => shaped.text.len(), - Self::Absolute(_) | Self::Fractional(_) | Self::Pin(_) => { - SPACING_REPLACE.len_utf8() - } + Self::Absolute(_) | Self::Fractional(_) => SPACING_REPLACE.len_utf8(), Self::Frame(_) | Self::Repeat(_, _) => NODE_REPLACE.len_utf8(), + Self::Pin(_) => PIN_REPLACE.len_utf8(), } } @@ -465,8 +466,9 @@ fn collect<'a>( let peeked = iter.peek().and_then(|(child, _)| match child { ParChild::Text(text) => text.chars().next(), ParChild::Quote { .. } => Some('"'), - ParChild::Spacing(_) | ParChild::Pin(_) => Some(SPACING_REPLACE), + ParChild::Spacing(_) => Some(SPACING_REPLACE), ParChild::Node(_) => Some(NODE_REPLACE), + ParChild::Pin(_) => Some(PIN_REPLACE), }); full.push_str(quoter.quote("es, double, peeked)); @@ -484,7 +486,7 @@ fn collect<'a>( Segment::Node(node) } &ParChild::Pin(idx) => { - full.push(SPACING_REPLACE); + full.push(PIN_REPLACE); Segment::Pin(idx) } }; diff --git a/src/library/utility/locate.rs b/src/library/utility/locate.rs deleted file mode 100644 index 0352199f..00000000 --- a/src/library/utility/locate.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::library::prelude::*; -use crate::model::LocateNode; - -/// Format content with access to its location on the page. -pub fn locate(_: &mut Machine, args: &mut Args) -> TypResult { - let node = LocateNode::new(args.expect("recipe")?); - Ok(Value::Content(Content::Locate(node))) -} diff --git a/src/library/utility/mod.rs b/src/library/utility/mod.rs index 32815607..10aa7c7a 100644 --- a/src/library/utility/mod.rs +++ b/src/library/utility/mod.rs @@ -1,12 +1,10 @@ //! Computational utility functions. mod color; -mod locate; mod math; mod string; pub use color::*; -pub use locate::*; pub use math::*; pub use string::*; -- cgit v1.2.3