From 4fadb4456672eaaaad85c6bf679a99ac8ea3499a Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sun, 8 Nov 2026 15:33:33 -0800 Subject: [PATCH] Type: a refused composite font edit leaves no new font in the font database The session now lists the new fonts' names before the edit, so sync removes a name the document does not define when the edit is refused. --- crates/engine/src/cmd/compositefonts.rs | 3 +++ crates/engine/src/cmd/compositefonts/tests.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/crates/engine/src/cmd/compositefonts.rs b/crates/engine/src/cmd/compositefonts.rs index 887e90515..3925612a1 100644 --- a/crates/engine/src/cmd/compositefonts.rs +++ b/crates/engine/src/cmd/compositefonts.rs @@ -187,6 +187,9 @@ fn replace(s: &mut Session, label: &str, after: Vec) -> Result<() } let changed: Vec = before.iter().filter(|b| !after.contains(b)).chain(after.iter().filter(|a| !before.contains(a))).map(|f| f.name.to_lowercase()).collect(); + // A refused or panicked edit leaves the document without the new fonts: `sync` forgets a name + // listed here that the document doesn't define. + s.composite_names.extend(after.iter().map(|f| f.name.to_lowercase())); let db = FontDb::global(); for f in &before { if !after.iter().any(|a| CompositeFont::same_name(&a.name, &f.name)) { diff --git a/crates/engine/src/cmd/compositefonts/tests.rs b/crates/engine/src/cmd/compositefonts/tests.rs index ae8bc5f8b..f51f066df 100644 --- a/crates/engine/src/cmd/compositefonts/tests.rs +++ b/crates/engine/src/cmd/compositefonts/tests.rs @@ -524,6 +524,21 @@ fn a_failed_batch_takes_back_its_composite_fonts() { assert!(db.composite_font("CF Failed Batch").is_none()); } +/// A composite font whose edit is refused, because it makes selected type too wide for the canvas, +/// is not left in the font database. +#[test] +fn a_refused_edit_takes_back_its_new_composite_font() { + let db = vectorcraft_text::FontDb::global(); + let mut s = session(); + let x = crate::MAX_COORD - 1000.0; + s.execute("text.create", &json!({"x": x, "y": 50, "text": "MMMMMMMM", "size": 100, "font": "CF Refused Edit"})).unwrap(); + let wide = json!({"name": "CF Refused Edit", "parts": {"kanji": {"font": "Source Sans 3", "size": 400}}}); + let e = s.execute("type.compositeFonts.set", &json!({"fonts": [wide]})).unwrap_err().to_string(); + assert!(e.contains("exceed the canvas"), "{e}"); + assert!(names(&s).is_empty()); + assert!(db.composite_font("CF Refused Edit").is_none()); +} + /// A loaded composite font cannot replace an installed family used by existing type. #[test] fn loaded_composite_font_cannot_take_an_installed_family_name() {