Merge r2 track t14: signatures

# Conflicts:
#	ATTRIBUTION.toml
#	crates/annot/src/tests.rs
This commit is contained in:
aiongg
2026-10-22 02:22:02 +00:00
26 changed files with 1025 additions and 95 deletions
+1 -1
View File
@@ -559,7 +559,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
c.push_str("h\n");
}
}
c.push_str("f*\n");
c.push_str("f\n");
return Some(form(rect, c.as_bytes(), res));
}
// A custom stamp: its picture (an image, or a form mapped to /PCPictureSize) fills
+1 -1
View File
@@ -394,7 +394,7 @@ pub enum Shape {
by: Option<String>,
},
/// A typed signature or initials: filled outlines (each contour as points normalised to
/// `rect`, 0–1, y up), drawn with the even-odd rule.
/// `rect`, 0–1, y up), drawn with the non-zero winding rule.
TypedSignature {
rect: [f64; 4],
contours: Vec<Vec<[f64; 2]>>,
+13
View File
@@ -1491,3 +1491,16 @@ fn page_walk_skips_repeated_and_cyclic_kids_without_queueing_them() {
assert_eq!(walk.next(), None);
assert_eq!(page_refs(&doc).unwrap(), [first, second]);
}
/// #1786: TrueType glyph contours (such as Inter's composite Ђ and ћ) overlap with the same
/// winding direction where strokes cross, so typed signature appearances must fill with the
/// non-zero winding operator (`f`), not even-odd (`f*`).
#[test]
fn typed_signature_uses_nonzero_winding_fill() {
let mut doc = fixture();
let contours = vec![vec![[0.4, 0.0], [0.6, 0.0], [0.6, 1.0], [0.4, 1.0]], vec![[0.0, 0.7], [1.0, 0.7], [1.0, 0.85], [0.0, 0.85]]];
let idx = add_annotation(&mut doc, &new(0, Shape::TypedSignature { rect: [100.0, 100.0, 200.0, 140.0], contours }), &meta("sig")).unwrap();
let ap = ap_content(&doc, &list(&doc, 0)[idx]);
assert!(ap.ends_with("h\nf\n"), "expected non-zero winding fill (`f`), got: {ap}");
assert!(!ap.contains("f*"), "must not use even-odd fill (`f*`): {ap}");
}