diff --git a/crates/organize/src/lib.rs b/crates/organize/src/lib.rs index c7f5c968a6..bdd038527e 100644 --- a/crates/organize/src/lib.rs +++ b/crates/organize/src/lib.rs @@ -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)))?; } diff --git a/crates/organize/src/tests.rs b/crates/organize/src/tests.rs index 5dad127057..1b17320825 100644 --- a/crates/organize/src/tests.rs +++ b/crates/organize/src/tests.rs @@ -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)); + } + } + } +}