mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-12 05:12:39 +00:00
Opening documents: index lookups in Document::check and the format-1 style upgrade (#2218)
* fix(doc): index items, threads and styles when opening a document * Apply review fixes - crates/doc/src/tests.rs * address review: borrow style names in pin_para_default --------- Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com> Co-authored-by: autocraft-bot[bot] <354215646+autocraft-bot[bot]@users.noreply.github.com>
This commit is contained in:
5 files changed
+78
-10
No files matched your search
@@ -312,12 +312,14 @@ fn upgrade(doc: &mut Document, from: u32) {
|
||||
/// is missing.
|
||||
fn pin_para_default<T: Clone>(doc: &mut Document, field: fn(&mut ParaAttrs) -> &mut Option<T>, old: T) {
|
||||
let unset = |a: &ParaAttrs| field(&mut a.clone()).is_none();
|
||||
// Every style is looked up by name: through one index, not a search of all styles each time.
|
||||
let index = doc.styles.para_index();
|
||||
let roots: std::collections::HashSet<String> = doc
|
||||
.styles
|
||||
.paragraph
|
||||
.iter()
|
||||
.filter_map(|s| {
|
||||
let chain = doc.styles.para_chain(&s.name);
|
||||
let chain = designcraft_doc::Styles::para_chain_by(&s.name, |n| index.get(n).copied());
|
||||
if chain.iter().all(|c| unset(&c.para)) { chain.first().map(|c| c.name.clone()) } else { None }
|
||||
})
|
||||
.collect();
|
||||
@@ -326,9 +328,10 @@ fn pin_para_default<T: Clone>(doc: &mut Document, field: fn(&mut ParaAttrs) -> &
|
||||
*field(&mut s.para) = Some(old.clone());
|
||||
}
|
||||
}
|
||||
let styles = doc.styles.clone();
|
||||
// Borrowed names: one entry per style already in memory, so no copy and no extra bound needed.
|
||||
let names: std::collections::HashSet<&str> = doc.styles.paragraph.iter().map(|s| s.name.as_str()).collect();
|
||||
let mut pin = |st: &mut Story| {
|
||||
for p in st.paras.iter_mut().filter(|p| styles.para(&p.style).is_none()) {
|
||||
for p in st.paras.iter_mut().filter(|p| !names.contains(p.style.as_str())) {
|
||||
let v = field(&mut p.para);
|
||||
if v.is_none() {
|
||||
*v = Some(old.clone());
|
||||
|
||||
@@ -355,6 +355,23 @@ fn format_1_keep_lines_without_mode_stays_all_lines() {
|
||||
assert!(!designcraft_doc::ParaProps::default().keep_all_lines);
|
||||
}
|
||||
|
||||
/// A format-1 file with many styles upgrades in time linear in them (each style's chain was
|
||||
/// found by searching every style, twice over).
|
||||
#[test]
|
||||
fn format_1_upgrade_of_many_styles_is_linear() {
|
||||
let mut d = Document::new(&NewDocument::default());
|
||||
let st = d.styles_mut();
|
||||
for i in 0..20_000 {
|
||||
st.paragraph.push(para_style(&format!("S{i}"), (i % 2 == 1).then(|| format!("S{}", i - 1)).as_deref(), None));
|
||||
}
|
||||
let bytes = save_v1(&d);
|
||||
let t = std::time::Instant::now();
|
||||
let back = load(&bytes).unwrap();
|
||||
assert!(t.elapsed() < std::time::Duration::from_secs(10), "{:?}", t.elapsed());
|
||||
assert_eq!(back.styles.para("S0").unwrap().para.keep_all_lines, Some(true));
|
||||
assert_eq!(back.styles.para("S1").unwrap().para.keep_all_lines, None, "based on S0, which is pinned");
|
||||
}
|
||||
|
||||
/// Format 1 wrote paragraph rules, text frame options and numbered lists in full, so their
|
||||
/// old defaults (black rules, auto-size from the top centre, lists continuing across stories)
|
||||
/// load as saved. New documents take InDesign's.
|
||||
|
||||
Reference in new issue
Block a user