mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-30 21:26:48 -06:00
Merge pull request #1985 from VoiceLessQ/fix/1588-story-newlines
Story: copy a paragraph's format for all new returns at once (part of #1588)
This commit is contained in:
@@ -384,6 +384,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m
|
||||
|
||||
Newest first.
|
||||
|
||||
- **2026-10-29** · Inserting text with many returns no longer takes time that grows with their square (part of #1588): each return copied its paragraph's format with its own insert, moving every format after it. Splitting 20,000 returns into paragraphs took 15.8 s; placing a text file of them now takes 0.2 s, and one of a million returns 5.5 s. No readiness percentage change.
|
||||
- **2026-10-28** · Discretionary hyphens (U+00AD) break in the single-line composer with automatic hyphenation on or off, matching the paragraph composer. Unbroken soft hyphens remain invisible and zero-width, and words containing them keep only their discretionary break points (#1955). No readiness percentage change.
|
||||
- **2026-10-28** · Autoflow no longer sizes the rest of a story by a frame that a Start Paragraph option (next column, frame, page, or odd or even page) ends early (#1209). With a title before a chapter that starts on the next odd page, it estimated a page per few characters, added up to 2000 pages (the autoflow limit) and removed them again: placing 2000 words took 36 s in the app, now 0.4 s, with the same pages. It looks past tracked-deleted paragraphs for the option, as composing does, and asks for every frame that start options and breaks force in one round: 200 one-line chapters on their own pages take 9 ms (58 ms before). A break and the start option it meets count once, and breaks that tracked changes delete or a hidden condition hides don't count. No readiness percentage change.
|
||||
- **2026-10-28** · IDML export writes the document's default `StoryPreference` in `Resources/Preferences.xml`, as InDesign does. Only each story carried one, and IDML readers that take the spread reading order from the document's (Okapi's IDML filter) failed on DesignCraft's files. No readiness percentage change.
|
||||
|
||||
+18
-5
@@ -385,11 +385,11 @@ impl Story {
|
||||
// Paragraph formats: each new '\n' splits the current paragraph; the new paragraphs copy it.
|
||||
let pi = self.para_at(pos);
|
||||
let newlines = text.bytes().filter(|b| *b == b'\n').count();
|
||||
if newlines > 0 {
|
||||
let f = self.paras[pi].clone();
|
||||
for _ in 0..newlines {
|
||||
self.paras.insert(pi + 1, f.clone());
|
||||
}
|
||||
if newlines > 0
|
||||
&& let Some(f) = self.paras.get(pi).cloned()
|
||||
{
|
||||
// All at once: an insert per return made many returns quadratic (#1588).
|
||||
self.paras.splice(pi + 1..pi + 1, std::iter::repeat_n(f, newlines));
|
||||
}
|
||||
self.text.insert_str(pos, text);
|
||||
// Character runs.
|
||||
@@ -669,6 +669,19 @@ mod tests {
|
||||
assert_eq!(s.para_ranges(), vec![0..6]);
|
||||
}
|
||||
|
||||
/// Each return inserted its paragraph format on its own, quadratic in the returns (#1588).
|
||||
#[test]
|
||||
fn many_returns_split_a_paragraph_at_once() {
|
||||
let para = ParaFormat { style: "Body".into(), ..ParaFormat::default() };
|
||||
let started = std::time::Instant::now();
|
||||
let s = Story::with_text(StoryId(1), &"\n".repeat(20_000), para.clone());
|
||||
let took = started.elapsed();
|
||||
assert!(took < std::time::Duration::from_secs(1), "took {took:?}");
|
||||
assert_eq!(s.paras.len(), 20_001);
|
||||
assert!(s.paras.iter().all(|p| *p == para));
|
||||
s.check().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_formats_split_and_merge() {
|
||||
let mut s = st("hello world");
|
||||
|
||||
Reference in New Issue
Block a user