diff --git a/crates/compose/src/lib.rs b/crates/compose/src/lib.rs index 9f91aa68f..075dc9872 100644 --- a/crates/compose/src/lib.rs +++ b/crates/compose/src/lib.rs @@ -648,6 +648,16 @@ pub fn compose(doc: &Document, story: &Story, frames: &[FrameSpec], opts: &Compo designcraft_doc::Leading::Points(v) => v, }; let spacing = spacing_for(&pp, base_size); + // An empty paragraph takes its height from its paragraph mark's character format. + let mark_chars = if glyphs.is_empty() { + std::borrow::Cow::Owned(doc.styles.resolve_char(&base_chars, story.char_format_at(prange.start))) + } else { + std::borrow::Cow::Borrowed(&base_chars) + }; + let mark_leading = match mark_chars.leading { + designcraft_doc::Leading::Auto => mark_chars.size * pp.auto_leading, + designcraft_doc::Leading::Points(v) => v, + }; // Paragraph start options. if force_col[pi] { cur.next_column(&cols); @@ -708,7 +718,7 @@ pub fn compose(doc: &Document, story: &Story, frames: &[FrameSpec], opts: &Compo for (k, b) in breaks.iter().enumerate() { let (s, e) = (g0 + b.start, g0 + b.end); let line_glyphs = &glyphs[s..e.max(s)]; - let (asc, desc, lead) = line_metrics(line_glyphs, &glyphs, s, base_leading, base_chars.size, db, &base_chars); + let (asc, desc, lead) = line_metrics(line_glyphs, &glyphs, s, mark_leading, mark_chars.size, db, &mark_chars); let mut baseline = cur.next_baseline(f, col, lead, asc, &pp); // Baseline grid. if let Some((g_start, inc)) = f.grid diff --git a/crates/compose/src/tests.rs b/crates/compose/src/tests.rs index 511a703a5..da3e46066 100644 --- a/crates/compose/src/tests.rs +++ b/crates/compose/src/tests.rs @@ -1027,3 +1027,20 @@ fn only_english_text_gets_english_hyphenation() { st.format_chars(0..n, |f| f.over.language = Some("French".into())); assert_eq!(hyphenated(&d2, sid), 0, "French isn't hyphenated with English rules"); } + +#[test] +fn empty_paragraph_takes_its_marks_format() { + // Paragraph style text is 12 pt (auto leading 14.4); every character, including the empty + // paragraph's mark, is 6 pt with 8 pt leading: the empty line must advance 8, not 14.4. + let text = "One\n\nTwo"; + let (mut d, sid, _) = doc_with(text, Rect::new(0.0, 0.0, 200.0, 200.0), ParaAttrs::default()); + d.story_mut(sid).unwrap().format_chars(0..text.len(), |f| { + f.over.size = Some(6.0); + f.over.leading = Some(designcraft_doc::Leading::Points(8.0)); + }); + let cs = compose_story(&d, sid, &ComposeOptions::default()); + let lines = all_lines(&cs); + assert_eq!(lines.len(), 3); + assert!((lines[1].baseline - lines[0].baseline - 8.0).abs() < 1e-6, "{} {}", lines[0].baseline, lines[1].baseline); + assert!((lines[2].baseline - lines[1].baseline - 8.0).abs() < 1e-6, "{} {}", lines[1].baseline, lines[2].baseline); +}