M4: resolve indirect initial-view boolean preferences

Read all six boolean ViewerPreferences through the document resolver. Synthetic regressions cover direct/indirect dictionaries, true/false, malformed values and save/reopen.
This commit is contained in:
Mex
2026-10-20 21:07:13 +02:00
committed by GitHub
parent 22bedbf2af
commit 3d32ffd27c
+48 -1
View File
@@ -96,7 +96,7 @@ pub fn initial_view(doc: &Document) -> InitialView {
..InitialView::default()
};
if let Some(vp) = c.get(b"ViewerPreferences").map(|o| doc.resolve(o)).and_then(|o| o.as_dict().cloned()) {
let flag = |k: &[u8]| matches!(vp.get(k), Some(Object::Bool(true)));
let flag = |k: &[u8]| matches!(vp.get(k).map(|o| doc.resolve(o)).as_deref(), Some(Object::Bool(true)));
v.fit_window = flag(b"FitWindow");
v.center_window = flag(b"CenterWindow");
v.display_title = flag(b"DisplayDocTitle");
@@ -248,3 +248,50 @@ pub fn set_initial_view(doc: &mut Document, v: &InitialView) -> Result<(), Organ
})?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use pdfcraft_cos::{SaveOptions, write_full};
use std::sync::Arc;
fn flags(view: InitialView) -> [bool; 6] {
[view.fit_window, view.center_window, view.display_title, view.hide_menubar, view.hide_toolbar, view.hide_window_ui]
}
#[test]
fn initial_view_resolves_indirect_boolean_preferences() {
let keys: [&[u8]; 6] = [b"FitWindow", b"CenterWindow", b"DisplayDocTitle", b"HideMenubar", b"HideToolbar", b"HideWindowUI"];
for enabled in [true, false] {
for indirect_dictionary in [false, true] {
let mut doc = Document::new_empty();
let boolean = doc.add(Object::Bool(enabled));
let mut preferences = Dict::new();
for key in keys {
preferences.set(key.to_vec(), Object::Ref(boolean));
}
let preferences = if indirect_dictionary { Object::Ref(doc.add(preferences)) } else { Object::Dict(preferences) };
let root = doc.root().unwrap();
doc.update_dict(root, |c| c.set(b"ViewerPreferences".to_vec(), preferences)).unwrap();
assert_eq!(flags(initial_view(&doc)), [enabled; 6]);
let saved = write_full(&doc, &SaveOptions::default()).unwrap();
let reopened = Document::open(Arc::new(saved)).unwrap();
assert_eq!(flags(initial_view(&reopened)), [enabled; 6]);
assert_eq!(displays_doc_title(&reopened), enabled);
}
}
}
#[test]
fn initial_view_malformed_boolean_preferences_keep_false_defaults() {
for value in [Object::Null, Object::Int(1), Object::name("true"), Object::Ref(pdfcraft_cos::ObjRef::new(999_999, 0))] {
let mut doc = Document::new_empty();
let value = doc.add(value);
let mut preferences = Dict::new();
preferences.set(b"FitWindow".to_vec(), Object::Ref(value));
let root = doc.root().unwrap();
doc.update_dict(root, |c| c.set(b"ViewerPreferences".to_vec(), Object::Dict(preferences))).unwrap();
assert_eq!(flags(initial_view(&doc)), [false; 6]);
}
}
}