An empty last paragraph isn't overset text, as in InDesign

A story that ends with a paragraph return has an empty last paragraph. When
it didn't fit, DesignCraft marked the story overset at the end of its text
(Preflight: "Overset text: 0 characters"; the out port turned red).
InDesign doesn't: Montilla Design's Flex Layout file has a caption ending
with a return, fitted to its three lines, and InDesign reports no errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
moppeeer
2026-10-15 01:40:50 +02:00
co-authored by Claude Opus 5.5
parent d07cbbe94c
commit ccf4f4aee4
3 changed files with 22 additions and 0 deletions
+1
View File
@@ -132,6 +132,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m
Newest first.
- **2026-10-15** · A story that ends with a return is no longer overset when only its empty last paragraph doesn't fit, as in InDesign (Preflight said "Overset text: 0 characters" for a caption InDesign shows with no errors). No readiness percentage change.
- **2026-10-13** · Object › Fitting has InDesign's shortcuts: Fill Frame Proportionally ⌘⌥⇧C, Fit Content Proportionally ⌘⌥⇧E, Fit Frame to Content ⌘⌥C, Fit Content to Frame ⌘⌥E, Center Content ⌘⇧E. No readiness percentage change.
- **2026-10-13** · Gradients between process colours blend as inks, as InDesign shows them: magenta to cyan passes through C 50 M 50 (a light lilac) on screen instead of the darker RGB mix, and a midpoint between CMYK or grey stops no longer turns the PDF shading RGB. No readiness percentage change.
- **2026-10-14** · The Swatches panel has InDesign's header: a Fill/Stroke proxy, Formatting Affects Container/Text and the Tint of the colour in front (a tint alone keeps each object's own swatch). Clicking a swatch applies it to the fill or stroke in front (of the text, when formatting affects text), and the bottom row has New Color Group, New Swatch and Delete Swatch. No readiness percentage change.
+5
View File
@@ -936,6 +936,11 @@ fn compose_with_db(doc: &Document, story: &Story, frames: &[FrameSpec], opts: &C
pi = j;
continue 'paras;
}
// An empty last paragraph (the story ends with a return) isn't overset text, as in
// InDesign: nothing of it is left to show.
if prange.is_empty() && prange.start >= story.text.len() {
break 'paras;
}
out.overset_at = Some(glyphs.get(g0).map(|g| g.byte).unwrap_or(prange.start));
// The part of the paragraph that fits keeps its shading and border.
para_box_decos(&mut out, pi, &pp);
+16
View File
@@ -4060,3 +4060,19 @@ fn empty_paragraphs_get_no_bullet_or_number() {
assert_eq!(list_labels(&cs, LABEL_CHARS), ["1.", "", "2.", ""], "list `{name}`");
}
}
/// A story that ends with a return isn't overset when only its empty last paragraph doesn't fit,
/// as in InDesign (Montilla Design's file: a caption fitted to its three lines, "No errors"). Text
/// that doesn't fit still is.
#[test]
fn an_empty_last_paragraph_isnt_overset() {
// 12 pt, 14.4 leading: two lines fit in 35 pt, a third (baseline ~40) doesn't.
let (d, sid, _) = doc_with("One\nTwo\n", Rect::new(0.0, 0.0, 200.0, 35.0), ParaAttrs::default());
let cs = compose_story(&d, sid, &ComposeOptions::default());
assert_eq!(all_lines(&cs).len(), 2);
assert!(!cs.is_overset(), "only the empty paragraph after the last return is left");
let (d, sid, _) = doc_with("One\nTwo\nThree", Rect::new(0.0, 0.0, 200.0, 35.0), ParaAttrs::default());
assert!(compose_story(&d, sid, &ComposeOptions::default()).is_overset());
let (d, sid, _) = doc_with("One\nTwo\n\n", Rect::new(0.0, 0.0, 200.0, 35.0), ParaAttrs::default());
assert!(compose_story(&d, sid, &ComposeOptions::default()).is_overset(), "an empty paragraph before the last one is text");
}