mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-26 11:08:48 -06:00
test(render): a reply finds its comment through a reference chain and a shared /Annots array
Rebasing onto main met its annotation listing fixes (c82dc91a,dfde9078): inspect now lists each annotation once, at the first page and position that lists it, told apart by the object its reference chain ends at, and reads a page-shared /Annots array under its first page only. The rebase collects reply slots in that same pass and matches /IRT by the object it resolves to, so a reply finds its comment wherever the listing keeps it. The test fails with the slots keyed by the raw /Annots reference (as before the rebase) and with /IRT matched by its raw reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
931b9a599a
commit
7c3dfe0a2a
@@ -2940,6 +2940,39 @@ trailer << /Root 1 0 R >>
|
||||
}
|
||||
}
|
||||
|
||||
/// A reply finds its comment where the listing keeps it: on the first page of a page-shared
|
||||
/// `/Annots` array, whether its `/IRT` names the comment or an object holding a reference to it.
|
||||
#[test]
|
||||
fn a_reply_finds_its_comment_through_a_reference_chain_and_a_shared_array() {
|
||||
let pdf = "%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n\
|
||||
2 0 obj << /Type /Pages /Kids [3 0 R 4 0 R] /Count 2 >> endobj\n\
|
||||
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Annots 7 0 R >> endobj\n\
|
||||
4 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Annots 7 0 R >> endobj\n\
|
||||
5 0 obj 6 0 R endobj\n\
|
||||
6 0 obj << /Type /Annot /Subtype /Text /Rect [0 0 1 1] /Contents (comment) >> endobj\n\
|
||||
7 0 obj [5 0 R 8 0 R 9 0 R] endobj\n\
|
||||
8 0 obj << /Type /Annot /Subtype /Text /Rect [0 0 1 1] /Contents (to the comment) /IRT 6 0 R >> endobj\n\
|
||||
9 0 obj << /Type /Annot /Subtype /Text /Rect [0 0 1 1] /Contents (through the chain) /IRT 5 0 R >> endobj\n\
|
||||
trailer << /Root 1 0 R >>\n%%EOF";
|
||||
let mut doc = Document::load_mem(pdf.as_bytes()).expect("loads");
|
||||
let mut saved = Vec::new();
|
||||
doc.save_to(&mut saved).expect("saves");
|
||||
let lazy = LazyStructure::new(Arc::new(saved), None).expect("opens");
|
||||
let page = PageInfo { width: 200.0, height: 200.0, crop: [0.0, 0.0, 200.0, 200.0], rotation: 0, label: String::new() };
|
||||
for reader in [&doc as &dyn Structure, &lazy] {
|
||||
let mut info = DocInfo { pages: vec![page.clone(), page.clone()], ..Default::default() };
|
||||
Inspector::new(reader).fill(&mut info);
|
||||
let notes = &info.annotations;
|
||||
assert_eq!(notes.len(), 3, "{notes:?}");
|
||||
let comment = notes.iter().find(|a| a.contents.as_deref() == Some("comment")).expect("listed");
|
||||
assert_eq!((comment.page, comment.index, comment.is_reply()), (0, 0, false));
|
||||
for reply in ["to the comment", "through the chain"] {
|
||||
let a = notes.iter().find(|a| a.contents.as_deref() == Some(reply)).expect("listed");
|
||||
assert_eq!((a.page, a.parent), (0, Some((0, 0))), "{reply}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A conversion rejected as too long, or trimmed short or to nothing, still spends the raw
|
||||
/// length, so a string many entries share is converted only a few times.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user