diff --git a/crates/render/tests/it/widgets_above_annotations.rs b/crates/render/tests/it/widgets_above_annotations.rs index a101569590..7800fa05cf 100644 --- a/crates/render/tests/it/widgets_above_annotations.rs +++ b/crates/render/tests/it/widgets_above_annotations.rs @@ -47,10 +47,15 @@ fn pdf(order: &str) -> Vec { /// The colour at the page's centre. fn centre(order: &str) -> [u8; 3] { + at(order, 100, 100) +} + +/// The colour at (`x`, `y`) px from the top left. +fn at(order: &str, x: usize, y: usize) -> [u8; 3] { let mut renderer = PageRenderer::new(Arc::new(pdf(order)), RenderConfig::default()); let out = renderer.render(RenderRequest { page: 0, scale: 1.0, ..Default::default() }); assert!(out.error.is_none(), "{:?}", out.error); - let at = (100 * out.width as usize + 100) * 4; + let at = (y * out.width as usize + x) * 4; let px = out.rgba.get(at..at + 3).expect("the centre lies on the page"); [px[0], px[1], px[2]] } @@ -62,4 +67,8 @@ fn a_widget_is_drawn_above_the_comments_on_its_page() { // Comments keep their `/Annots` order among themselves. assert_eq!(centre("RS"), [0, 0, 0], "the black square listed last is on top"); assert_eq!(centre("SR"), [255, 0, 0], "the red square listed last is on top"); + // And with a widget among them: (45, 45) is inside both squares, outside the check box. + assert_eq!(at("WRS", 45, 45), [0, 0, 0], "a widget first: the black square listed last is on top"); + assert_eq!(at("WSR", 45, 45), [255, 0, 0], "a widget first: the red square listed last is on top"); + assert_eq!(centre("WSR"), [0, 255, 0], "and the check box above both"); } diff --git a/vendor/hayro-interpret/src/interpret/mod.rs b/vendor/hayro-interpret/src/interpret/mod.rs index 6f380f07b4..d881ad2f24 100644 --- a/vendor/hayro-interpret/src/interpret/mod.rs +++ b/vendor/hayro-interpret/src/interpret/mod.rs @@ -203,9 +203,12 @@ pub fn interpret_page<'a>( // PdfCraft patch (86): form fields' widgets are drawn after the page's other // annotations, each group in `/Annots` order, as other readers draw them: a filled // comment listed after a check box covered the box. ISO 32000-2 doesn't order the two. - let mut annots: Vec> = annot_arr.iter::>().collect(); - annots.sort_by_key(|a| a.get::>(SUBTYPE).as_deref() == Some(b"Widget")); - for annot in annots { + // Two passes over the array, so nothing is held for every entry of a long one. + for widgets in [false, true] { + for annot in annot_arr.iter::>() { + if (annot.get::>(SUBTYPE).as_deref() == Some(b"Widget")) != widgets { + continue; + } let flags = annot.get::(F).unwrap_or(0); // Annotation should be hidden (Hidden = bit 2, NoView = bit 6). @@ -321,6 +324,7 @@ pub fn interpret_page<'a>( draw_highlight_without_appearance(&annot, context, device); } } + } device.end_annotations(); } }