From f69c3fb1e5b6e331a2adf0fa342d7793cdf615ad Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 20 Nov 2022 20:11:12 +0100 Subject: [PATCH] Refactor building --- library/src/core/behave.rs | 2 +- library/src/layout/mod.rs | 160 ++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 85 deletions(-) diff --git a/library/src/core/behave.rs b/library/src/core/behave.rs index 29d5dc490..8558facae 100644 --- a/library/src/core/behave.rs +++ b/library/src/core/behave.rs @@ -28,7 +28,7 @@ pub enum Behaviour { Supportive, /// A node that destroys adjacent weak nodes. Destructive, - /// A node that does not interact at all with other node, having the + /// A node that does not interact at all with other nodes, having the /// same effect as if it didn't exist. Ignorant, } diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs index daa7b8a1d..7b11177b9 100644 --- a/library/src/layout/mod.rs +++ b/library/src/layout/mod.rs @@ -322,8 +322,7 @@ impl<'a> Builder<'a> { if let Some(realized) = styles.show(self.world, content)? { let stored = self.scratch.content.alloc(realized); - self.accept(stored, styles)?; - return Ok(()); + return self.accept(stored, styles); } if self.list.accept(content, styles) { @@ -353,7 +352,9 @@ impl<'a> Builder<'a> { self.interrupt(Interruption::Page, styles, keep)?; if let Some(doc) = &mut self.doc { - doc.accept(content, styles); + if doc.accept(content, styles) { + return Ok(()); + } } // We might want to issue a warning or error for content that wasn't @@ -402,20 +403,32 @@ impl<'a> Builder<'a> { styles: StyleChain<'a>, keep: bool, ) -> SourceResult<()> { - if intr >= Interruption::List && !self.list.is_empty() { - mem::take(&mut self.list).finish(self)?; + if intr >= Interruption::List && !self.list.items.is_empty() { + let staged = mem::take(&mut self.list.staged); + let (list, styles) = mem::take(&mut self.list).finish(); + let stored = self.scratch.content.alloc(list); + self.accept(stored, styles)?; + for (content, styles) in staged { + self.accept(content, styles)?; + } } - if intr >= Interruption::Par && !self.par.is_empty() { - mem::take(&mut self.par).finish(self); + if intr >= Interruption::Par && !self.par.0.is_empty() { + let (par, styles) = mem::take(&mut self.par).finish(); + let stored = self.scratch.content.alloc(par); + self.accept(stored, styles)?; } - if intr >= Interruption::Page { - if let Some(doc) = &mut self.doc { - if !self.flow.is_empty() || (doc.keep_next && keep) { - mem::take(&mut self.flow).finish(doc, styles); - } - doc.keep_next = !keep; + if let Some(doc) = &mut self.doc { + if intr >= Interruption::Page + && (!self.flow.0.is_empty() || (doc.keep_next && keep)) + { + let (flow, shared) = mem::take(&mut self.flow).finish(); + let styles = + if shared == StyleChain::default() { styles } else { shared }; + let page = PageNode(flow).pack(); + let stored = self.scratch.content.alloc(page); + self.accept(stored, styles)?; } } @@ -443,15 +456,19 @@ struct DocBuilder<'a> { } impl<'a> DocBuilder<'a> { - fn accept(&mut self, content: &Content, styles: StyleChain<'a>) { + fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool { if let Some(pagebreak) = content.downcast::() { self.keep_next = !pagebreak.weak; + return true; } if let Some(page) = content.downcast::() { self.pages.push(page.clone(), styles); self.keep_next = false; + return true; } + + false } } @@ -466,32 +483,35 @@ impl Default for DocBuilder<'_> { struct FlowBuilder<'a>(BehavedBuilder<'a>, bool); impl<'a> FlowBuilder<'a> { - fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool { - let last_was_parbreak = std::mem::replace(&mut self.1, false); - + fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool { if content.is::() { self.1 = true; return true; - } else if content.is::() || content.is::() { + } + + let last_was_parbreak = self.1; + self.1 = false; + + if content.is::() || content.is::() { self.0.push(content.clone(), styles); return true; - } else if content.has::() { - if !last_was_parbreak { - let tight = if let Some(node) = content.downcast::() { - node.tight - } else if let Some(node) = content.downcast::() { - node.tight - } else if let Some(node) = content.downcast::() { - node.tight - } else { - false - }; + } - if tight { - let leading = styles.get(ParNode::LEADING); - let spacing = VNode::list_attach(leading.into()); - self.0.push(spacing.pack(), styles); - } + if content.has::() { + let is_tight_list = if let Some(node) = content.downcast::() { + node.tight + } else if let Some(node) = content.downcast::() { + node.tight + } else if let Some(node) = content.downcast::() { + node.tight + } else { + false + }; + + if !last_was_parbreak && is_tight_list { + let leading = styles.get(ParNode::LEADING); + let spacing = VNode::list_attach(leading.into()); + self.0.push(spacing.pack(), styles); } let above = styles.get(BlockNode::ABOVE); @@ -505,15 +525,9 @@ impl<'a> FlowBuilder<'a> { false } - fn finish(self, doc: &mut DocBuilder<'a>, styles: StyleChain<'a>) { + fn finish(self) -> (Content, StyleChain<'a>) { let (flow, shared) = self.0.finish(); - let styles = if flow.is_empty() { styles } else { shared }; - let node = PageNode(FlowNode(flow).pack()); - doc.pages.push(node, styles); - } - - fn is_empty(&self) -> bool { - self.0.is_empty() + (FlowNode(flow).pack(), shared) } } @@ -522,7 +536,7 @@ impl<'a> FlowBuilder<'a> { struct ParBuilder<'a>(BehavedBuilder<'a>); impl<'a> ParBuilder<'a> { - fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool { + fn accept(&mut self, content: &'a Content, styles: StyleChain<'a>) -> bool { if content.is::() || content.is::() || content.is::() @@ -537,15 +551,9 @@ impl<'a> ParBuilder<'a> { false } - fn finish(self, parent: &mut Builder<'a>) { + fn finish(self) -> (Content, StyleChain<'a>) { let (children, shared) = self.0.finish(); - if !children.is_empty() { - parent.flow.accept(&ParNode(children).pack(), shared); - } - } - - fn is_empty(&self) -> bool { - self.0.is_empty() + (ParNode(children).pack(), shared) } } @@ -565,50 +573,34 @@ impl<'a> ListBuilder<'a> { && (content.is::() || content.is::()) { self.staged.push((content, styles)); - } else if let Some(item) = content.downcast::() { + return true; + } + + if let Some(item) = content.downcast::() { if self .items .items() .next() - .map_or(false, |first| item.kind() != first.kind()) + .map_or(true, |first| item.kind() == first.kind()) { - return false; + self.items.push(item.clone(), styles); + self.tight &= self.staged.drain(..).all(|(t, _)| !t.is::()); + return true; } - - self.items.push(item.clone(), styles); - self.tight &= self.staged.drain(..).all(|(t, _)| !t.is::()); - } else { - return false; } - true + false } - fn finish(self, parent: &mut Builder<'a>) -> SourceResult<()> { + fn finish(self) -> (Content, StyleChain<'a>) { let (items, shared) = self.items.finish(); - if let Some(item) = items.items().next() { - let tight = self.tight; - let content = match item.kind() { - LIST => ListNode:: { tight, items }.pack(), - ENUM => ListNode:: { tight, items }.pack(), - DESC | _ => ListNode:: { tight, items }.pack(), - }; - - let stored = parent.scratch.content.alloc(content); - parent.accept(stored, shared)?; - } - - for (content, styles) in self.staged { - parent.accept(content, styles)?; - } - - parent.list.tight = true; - - Ok(()) - } - - fn is_empty(&self) -> bool { - self.items.is_empty() + let item = items.items().next().unwrap(); + let output = match item.kind() { + LIST => ListNode:: { tight: self.tight, items }.pack(), + ENUM => ListNode:: { tight: self.tight, items }.pack(), + DESC | _ => ListNode:: { tight: self.tight, items }.pack(), + }; + (output, shared) } }