summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-11-17 12:40:58 +0100
committerLaurenz <laurmaedje@gmail.com>2022-11-17 12:46:26 +0100
commitcabd0908e230e451bd9f1394390f8c5deb17182e (patch)
tree665fe796b8487a0913fbc35aeed527c20050eca3
parentbf59c08a0a601eeac4354c505cab15e65601c8e8 (diff)
Handle paragraph indent at a later stage
-rw-r--r--library/src/layout/flow.rs19
-rw-r--r--library/src/layout/mod.rs45
-rw-r--r--library/src/text/par.rs20
3 files changed, 46 insertions, 38 deletions
diff --git a/library/src/layout/flow.rs b/library/src/layout/flow.rs
index b05146c9..f47a8f42 100644
--- a/library/src/layout/flow.rs
+++ b/library/src/layout/flow.rs
@@ -1,3 +1,5 @@
+use typst::model::{Property, StyleEntry};
+
use super::{AlignNode, ColbreakNode, PlaceNode, Spacing, VNode};
use crate::prelude::*;
use crate::text::ParNode;
@@ -58,6 +60,8 @@ struct FlowLayouter {
used: Size,
/// The sum of fractions in the current region.
fr: Fr,
+ /// Whether the last block was a paragraph.
+ last_block_was_par: bool,
/// Spacing and layouted blocks.
items: Vec<FlowItem>,
/// Finished frames for previous regions.
@@ -92,6 +96,7 @@ impl FlowLayouter {
full,
used: Size::zero(),
fr: Fr::zero(),
+ last_block_was_par: false,
items: vec![],
finished: vec![],
}
@@ -150,8 +155,18 @@ impl FlowLayouter {
.unwrap_or(Align::Top),
);
+ // Disable paragraph indent if this is not a consecutive paragraph.
+ let reset;
+ let is_par = block.is::<ParNode>();
+ let mut chained = styles;
+ if !self.last_block_was_par && is_par && !styles.get(ParNode::INDENT).is_zero() {
+ let property = Property::new(ParNode::INDENT, Length::zero());
+ reset = StyleEntry::Property(property);
+ chained = reset.chain(&styles);
+ }
+
// Layout the block itself.
- let frames = block.layout_block(world, &self.regions, styles)?;
+ let frames = block.layout_block(world, &self.regions, chained)?;
let len = frames.len();
for (i, frame) in frames.into_iter().enumerate() {
// Grow our size, shrink the region and save the frame for later.
@@ -166,6 +181,8 @@ impl FlowLayouter {
}
}
+ self.last_block_was_par = is_par;
+
Ok(())
}
diff --git a/library/src/layout/mod.rs b/library/src/layout/mod.rs
index d6bc9175..f79da71c 100644
--- a/library/src/layout/mod.rs
+++ b/library/src/layout/mod.rs
@@ -474,13 +474,14 @@ struct FlowBuilder<'a>(BehavedBuilder<'a>, bool);
impl<'a> FlowBuilder<'a> {
fn accept(&mut self, content: &Content, styles: StyleChain<'a>) -> bool {
- let last_was_parbreak = self.1;
- self.1 = false;
+ let last_was_parbreak = std::mem::replace(&mut self.1, false);
if content.is::<ParbreakNode>() {
self.1 = true;
+ return true;
} else if content.is::<VNode>() || content.is::<ColbreakNode>() {
self.0.push(content.clone(), styles);
+ return true;
} else if content.has::<dyn LayoutBlock>() {
if !last_was_parbreak {
let tight = if let Some(node) = content.downcast::<ListNode>() {
@@ -505,11 +506,10 @@ impl<'a> FlowBuilder<'a> {
self.0.push(above.pack(), styles);
self.0.push(content.clone(), styles);
self.0.push(below.pack(), styles);
- } else {
- return false;
+ return true;
}
- true
+ false
}
fn finish(self, doc: &mut DocBuilder<'a>, styles: StyleChain<'a>) {
@@ -545,39 +545,10 @@ impl<'a> ParBuilder<'a> {
}
fn finish(self, parent: &mut Builder<'a>) {
- let (mut children, shared) = self.0.finish();
- if children.is_empty() {
- return;
+ let (children, shared) = self.0.finish();
+ if !children.is_empty() {
+ parent.flow.accept(&ParNode(children).pack(), shared);
}
-
- // Paragraph indent should only apply if the paragraph starts with
- // text and follows directly after another paragraph.
- let indent = shared.get(ParNode::INDENT);
- if !indent.is_zero()
- && children
- .items()
- .find_map(|child| {
- if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
- Some(true)
- } else if child.has::<dyn LayoutInline>() {
- Some(false)
- } else {
- None
- }
- })
- .unwrap_or_default()
- && parent
- .flow
- .0
- .items()
- .rev()
- .find(|child| child.has::<dyn LayoutBlock>())
- .map_or(false, |child| child.is::<ParNode>())
- {
- children.push_front(HNode::strong(indent.into()).pack());
- }
-
- parent.flow.accept(&ParNode(children).pack(), shared);
}
fn is_empty(&self) -> bool {
diff --git a/library/src/text/par.rs b/library/src/text/par.rs
index 3e72b034..df02bc3c 100644
--- a/library/src/text/par.rs
+++ b/library/src/text/par.rs
@@ -393,6 +393,26 @@ fn collect<'a>(
let mut segments = vec![];
let mut iter = par.0.iter().peekable();
+ let indent = styles.get(ParNode::INDENT);
+ if !indent.is_zero()
+ && par
+ .0
+ .items()
+ .find_map(|child| {
+ if child.is::<TextNode>() || child.is::<SmartQuoteNode>() {
+ Some(true)
+ } else if child.has::<dyn LayoutInline>() {
+ Some(false)
+ } else {
+ None
+ }
+ })
+ .unwrap_or_default()
+ {
+ full.push(SPACING_REPLACE);
+ segments.push((Segment::Spacing(indent.into()), *styles));
+ }
+
while let Some((child, map)) = iter.next() {
let styles = map.chain(styles);
let segment = if child.is::<SpaceNode>() {