M4: accumulate repeated page rotation indices

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.
This commit is contained in:
Mex
2026-10-18 11:51:29 +02:00
committed by GitHub
parent 5af8e88fca
commit 19d138e951
2 changed files with 36 additions and 1 deletions
+4 -1
View File
@@ -205,7 +205,10 @@ pub fn rotate_pages(doc: &mut Document, indices: &[usize], degrees: i64) -> Resu
let delta = degrees.rem_euclid(360);
for &i in indices {
let (page, inherited) = &all[i];
let current = resolved_rotation(doc, inherited);
// Repeated indices must see earlier edits instead of the page walk's snapshot.
let current_page = doc.get(*page);
let current_attrs = current_page.as_dict().filter(|attrs| attrs.get(b"Rotate").is_some()).unwrap_or(inherited);
let current = resolved_rotation(doc, current_attrs);
let new = (current.rem_euclid(360) + delta).rem_euclid(360);
doc.update_dict(*page, |d| d.set(b"Rotate".to_vec(), Object::Int(new)))?;
}
+32
View File
@@ -2723,3 +2723,35 @@ fn a_chain_of_objects_too_deep_to_copy_is_refused_and_leaves_the_destination_alo
.join();
assert!(run.is_ok(), "the copy must not overflow the stack");
}
#[test]
fn rotate_repeated_indices_accumulate_from_the_current_page_value() {
for level in 0..3 {
for indices in [vec![0, 0], vec![0, 1, 0]] {
let mut doc = open(fixture());
let rotation = doc.add(Object::Int(90));
let page = pages(&doc).unwrap()[0].obj;
let target = match level {
0 => page,
1 => doc.get(page).as_dict().unwrap().reference(b"Parent").unwrap(),
_ => pages_root(&doc).unwrap(),
};
doc.update_dict(target, |d| d.set(b"Rotate".to_vec(), Object::Ref(rotation))).unwrap();
let mut doc = open(write_full(&doc, &SaveOptions::default()).unwrap());
let rotation = walk(&doc).unwrap()[0].1.reference(b"Rotate").unwrap();
let original_labels = labels(&doc);
rotate_pages(&mut doc, &indices, 90).unwrap();
assert_eq!(page_rotation(&doc, 0).unwrap(), 270, "level {level}, indices {indices:?}");
assert_eq!(*doc.get(rotation), Object::Int(90), "shared source angle is unchanged");
for saved in [write_incremental(&doc, &SaveOptions::default()).unwrap(), write_full(&doc, &SaveOptions::default()).unwrap()] {
let reopened = open(saved.clone());
assert_eq!(page_rotation(&reopened, 0).unwrap(), 270);
assert_eq!(page_rotation(&reopened, 1).unwrap(), if indices.len() == 3 { 180 } else { 90 });
assert_eq!(page_rotation(&reopened, 2).unwrap(), 90);
assert_eq!(labels(&reopened), original_labels);
let independent = hayro_syntax::Pdf::new(saved).unwrap();
assert_eq!(independent.pages()[0].render_dimensions(), (400.0, 300.0));
}
}
}
}