mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-10 13:01:29 +00:00
M5: a callout given its arrow point alone keeps its knee (#1152)
comment_edit with one point on a callout whose /CL has six numbers built the new line from that point and the end only, so the knee was dropped without a word. An agent moving just the arrow lost the knee. place_text_box now keeps the old knee when only the arrow point is given; two points still set both, and a four-number /CL still gains a knee only when one is sent. The points schema says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pq7HyCfwzyRXj4VfQAVVdv
This commit is contained in:
1 parent
a36dcbb3bc
commit
24ac313428
3 files changed
+25
-2
No files matched your search
@@ -413,7 +413,7 @@ pub fn set_points(doc: &mut Document, page: usize, index: usize, points: &[[f64;
|
||||
}
|
||||
if d.name(b"Subtype") == Some(b"FreeText") && callout_line(doc, &d).is_some() {
|
||||
// A callout's points: its arrow point, then optionally its knee (a four-number `/CL`
|
||||
// gains one; ISO 32000-2 Table 177 allows both forms).
|
||||
// gains one; ISO 32000-2 Table 177 allows both forms). The arrow point alone keeps a knee.
|
||||
if !matches!(points.len(), 1 | 2) || !finite(&points.concat()) {
|
||||
return Err(AnnotError::Invalid("a callout has an arrow point and, optionally, a knee".into()));
|
||||
}
|
||||
@@ -545,6 +545,15 @@ fn place_text_box(doc: &mut Document, r: ObjRef, rect: [f64; 4], lead: Option<&[
|
||||
let old_line = callout_line(doc, &d);
|
||||
let old_box = callout_text_box(doc, &d);
|
||||
let old_end = old_line.as_deref().and_then(<[[f64; 2]]>::last).copied();
|
||||
// An arrow point alone moves the arrow: a knee the line has stays where it is.
|
||||
let kept: [[f64; 2]; 2];
|
||||
let lead = match (lead, old_line.as_deref()) {
|
||||
(Some([point]), Some([_, knee, _])) => {
|
||||
kept = [*point, *knee];
|
||||
Some(&kept[..])
|
||||
}
|
||||
_ => lead,
|
||||
};
|
||||
let line: Option<Vec<[f64; 2]>> = match (lead, old_line.as_deref()) {
|
||||
(Some(lead @ [.., toward]), _) => {
|
||||
let side = callout_side(rect, *toward);
|
||||
|
||||
@@ -2446,3 +2446,17 @@ fn summaries_give_no_callout_points_without_a_text_box() {
|
||||
assert_eq!((s.points.len(), s.text_box), (0, None), "/RD {rd:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Review on #4094: a callout given its arrow point alone keeps its knee. The new line was built
|
||||
/// from the one point and the end, so a six-number `/CL` silently became four.
|
||||
#[test]
|
||||
fn a_callouts_arrow_point_alone_keeps_its_knee() {
|
||||
let (mut doc, c) = callout_fixture();
|
||||
let before = nums(&list(&doc, 0)[c], b"CL");
|
||||
assert_eq!(before.len(), 6, "{before:?}");
|
||||
set_points(&mut doc, 0, c, &[[190.0, 500.0]], &meta("p")).unwrap();
|
||||
let after = nums(&list(&doc, 0)[c], b"CL");
|
||||
assert_eq!(after.len(), 6, "the knee stays: {after:?}");
|
||||
assert_eq!(after[..2], [190.0, 500.0], "the arrow point moved");
|
||||
assert_eq!(after[2..], before[2..], "the knee and the end are where they were");
|
||||
}
|
||||
@@ -916,7 +916,7 @@ pub fn tools() -> Vec<ToolDef> {
|
||||
"font_size": { "type": "number", "minimum": 1, "maximum": 400, "description": "Font size in points of a text box, typewriter text or callout; the box grows to hold the text." },
|
||||
"rect": { "type": "array", "items": { "type": "number" }, "minItems": 4, "maxItems": 4 },
|
||||
"move": point(),
|
||||
"points": { "type": "array", "items": point(), "minItems": 1, "description": "A line's two ends, every corner of connected lines, a polygon or a cloud, or a callout's arrow point and (optionally) knee, in page coordinates." },
|
||||
"points": { "type": "array", "items": point(), "minItems": 1, "description": "A line's two ends, every corner of connected lines, a polygon or a cloud, or a callout's arrow point and (optionally) knee, in page coordinates. A callout given its arrow point alone keeps the knee it has." },
|
||||
})),
|
||||
&["doc"],
|
||||
)),
|
||||
|
||||
Reference in new issue
Block a user