diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index e116f1594..1032ba546 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -33,7 +33,7 @@ use typst::frame::Frame; use typst::geom::*; use typst::model::{ capability, Barrier, Content, Node, SequenceNode, Show, StyleChain, StyleEntry, - StyleMap, StyleVec, StyleVecBuilder, StyledNode, Target, + StyleVec, StyleVecBuilder, StyledNode, Target, }; use typst::World; @@ -253,8 +253,10 @@ struct Builder<'a> { struct Scratch<'a> { /// An arena where intermediate style chains are stored. styles: Arena>, + /// An arena for individual intermediate style entries. + entries: Arena, /// An arena where intermediate content resulting from show rules is stored. - templates: Arena, + content: Arena, } /// Determines whether a style could interrupt some composable structure. @@ -305,7 +307,7 @@ impl<'a> Builder<'a> { ) -> SourceResult<()> { if let Some(text) = content.downcast::() { if let Some(realized) = styles.apply(self.world, Target::Text(&text.0))? { - let stored = self.scratch.templates.alloc(realized); + let stored = self.scratch.content.alloc(realized); return self.accept(stored, styles); } } else if let Some(styled) = content.downcast::() { @@ -357,16 +359,18 @@ impl<'a> Builder<'a> { content: &'a Content, styles: StyleChain<'a>, ) -> SourceResult { - let Some(mut realized) = styles.apply(self.world, Target::Node(content))? else { + let barrier = StyleEntry::Barrier(Barrier::new(content.id())); + let styles = self + .scratch + .entries + .alloc(barrier) + .chain(self.scratch.styles.alloc(styles)); + + let Some(realized) = styles.apply(self.world, Target::Node(content))? else { return Ok(false); }; - let mut map = StyleMap::new(); - let barrier = Barrier::new(content.id()); - map.push(StyleEntry::Barrier(barrier)); - map.push(StyleEntry::Barrier(barrier)); - realized = realized.styled_with_map(map); - let stored = self.scratch.templates.alloc(realized); + let stored = self.scratch.content.alloc(realized); self.accept(stored, styles)?; Ok(true) @@ -680,7 +684,7 @@ impl<'a> ListBuilder<'a> { DESC | _ => ListNode:: { tight, attached, items }.pack(), }; - let stored = parent.scratch.templates.alloc(content); + let stored = parent.scratch.content.alloc(content); parent.accept(stored, shared)?; for (content, styles) in self.staged { diff --git a/library/src/text/mod.rs b/library/src/text/mod.rs index a81647273..c2a675471 100644 --- a/library/src/text/mod.rs +++ b/library/src/text/mod.rs @@ -25,7 +25,7 @@ use self::quotes::*; use crate::prelude::*; /// A single run of text with the same style. -#[derive(Debug, Clone, Hash)] +#[derive(Clone, Hash)] pub struct TextNode(pub EcoString); impl TextNode { @@ -169,6 +169,12 @@ impl TextNode { } } +impl Debug for TextNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Text({:?})", self.0) + } +} + /// A lowercased font family like "arial". #[derive(Clone, Eq, PartialEq, Hash)] pub struct FontFamily(EcoString); diff --git a/src/model/content.rs b/src/model/content.rs index bc25cd79c..3851d38d2 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -115,10 +115,14 @@ impl Content { pub fn styled_with_entry(mut self, entry: StyleEntry) -> Self { if let Some(styled) = self.try_downcast_mut::() { styled.map.apply(entry); - return self; + self + } else if let Some(styled) = self.downcast::() { + let mut map = styled.map.clone(); + map.apply(entry); + StyledNode { sub: styled.sub.clone(), map }.pack() + } else { + StyledNode { sub: self, map: entry.into() }.pack() } - - StyledNode { sub: self, map: entry.into() }.pack() } /// Style this content with a full style map. diff --git a/src/model/styles.rs b/src/model/styles.rs index 8e7319420..62e3188ff 100644 --- a/src/model/styles.rs +++ b/src/model/styles.rs @@ -85,6 +85,15 @@ impl StyleMap { /// Like [`chain`](Self::chain) or [`apply_map`](Self::apply_map), but with /// only a entry. pub fn apply(&mut self, entry: StyleEntry) { + if let StyleEntry::Guard(a) = &entry { + if let [StyleEntry::Unguard(b), ..] = self.0.as_slice() { + if a == b { + self.0.remove(0); + return; + } + } + } + self.0.insert(0, entry); } @@ -124,7 +133,7 @@ impl From for StyleMap { impl Debug for StyleMap { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - for entry in self.0.iter().rev() { + for entry in self.0.iter() { writeln!(f, "{:?}", entry)?; } Ok(()) @@ -351,7 +360,7 @@ impl<'a> StyleChain<'a> { impl Debug for StyleChain<'_> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - for entry in self.entries() { + for entry in self.entries().collect::>().into_iter().rev() { writeln!(f, "{:?}", entry)?; } Ok(()) diff --git a/src/util/mod.rs b/src/util/mod.rs index c6809d235..0b6812237 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -161,9 +161,13 @@ impl ReadableTypeId { impl Debug for ReadableTypeId { fn fmt(&self, f: &mut Formatter) -> fmt::Result { #[cfg(debug_assertions)] - f.pad(self.name)?; + if let Some(part) = self.name.split("::").last() { + f.pad(part)?; + } + #[cfg(not(debug_assertions))] f.pad("ReadableTypeId")?; + Ok(()) } }