diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index b5c639182..a3f7d0bbc 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -4413,6 +4413,13 @@ impl Session { } } note_warnings(&mut info.warnings, &doc.xfa_warnings); + // As in `build_document`: the inspection reads only `/Info`, so fields stated only in XMP + // are filled in again after every full refresh. + for (field, value) in info_fields(&mut info, &editor.cos) { + if field.is_none() { + *field = value; + } + } doc.info = info; doc.fonts_stale = false; let mut form = pdfcraft_forms::fields(&editor.cos); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 7a739f256..bc490e2c5 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -555,6 +555,14 @@ fn document_information_stated_only_in_xmp_is_shown() { assert_eq!((doc.info.title.as_deref(), doc.info.author.as_deref(), doc.info.subject.as_deref()), (Some("Quarterly report"), Some("Ada"), None)); assert_eq!(doc.info_value("Title").as_deref(), Some("Quarterly report")); assert_eq!(doc.info_value("Author").as_deref(), Some("Ada")); + + // A full refresh (any structural edit, undo, redo) reads /Info again and must not lose them. + s.apply(id, Edit::RotatePages { pages: vec![0], degrees: 90 }).unwrap(); + let doc = s.get(id).unwrap(); + assert_eq!((doc.info.title.as_deref(), doc.info.author.as_deref()), (Some("Quarterly report"), Some("Ada")), "after an edit"); + s.undo(id).unwrap(); + let doc = s.get(id).unwrap(); + assert_eq!((doc.info.title.as_deref(), doc.info.author.as_deref()), (Some("Quarterly report"), Some("Ada")), "after undo"); } #[test]