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.
This commit is contained in:
dotCooCoo
2026-11-08 15:33:33 -08:00
parent 9a312e8ada
commit 4fadb44566
2 changed files with 18 additions and 0 deletions
+3
View File
@@ -187,6 +187,9 @@ fn replace(s: &mut Session, label: &str, after: Vec<CompositeFont>) -> Result<()
}
let changed: Vec<String> =
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)) {
@@ -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() {