mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 18:17:44 -06:00
Merge PR #2840: M6: detected form fields get no border or fill
crates/engine/src/js.rs: auto_detect_fields keeps main's comb and turn handling, builds props with no border and no fill for every field, and pushes SetFieldProps unconditionally (the review's fix) parity/acrobat-features.toml: form.detect-fields keeps main's comb evidence and notes and adds the no-border test and sentence
This commit is contained in:
@@ -349,7 +349,12 @@ impl Session {
|
||||
pdfcraft_forms::detect::Kind::CheckBox => (pdfcraft_forms::NewField::CheckBox, None),
|
||||
pdfcraft_forms::detect::Kind::Comb { cells } => (pdfcraft_forms::NewField::Text { multiline: false }, Some(cells)),
|
||||
};
|
||||
let mut props = FieldProps::default();
|
||||
// The page already draws the line or box the field sits on, so the field gets no
|
||||
// border or fill of its own: an opaque fill would hide the printed form (#294, #2831).
|
||||
let mut props = FieldProps {
|
||||
appearance: Some(pdfcraft_forms::LookPatch { border: Some(None), fill: Some(None), ..Default::default() }),
|
||||
..Default::default()
|
||||
};
|
||||
if turn != 0 {
|
||||
// A turned field keeps its place: the rectangle is already the one on the page.
|
||||
props.rotation = Some((0, turn));
|
||||
@@ -360,9 +365,7 @@ impl Session {
|
||||
props.flags = vec![(pdfcraft_forms::flags::COMB, true)];
|
||||
}
|
||||
edits.push(Edit::AddField { page, rect: c.rect, kind, name: Some(c.name.clone()) });
|
||||
if turn != 0 || comb.is_some() {
|
||||
edits.push(Edit::SetFieldProps { name: c.name, props: Box::new(props) });
|
||||
}
|
||||
edits.push(Edit::SetFieldProps { name: c.name, props: Box::new(props) });
|
||||
}
|
||||
self.apply(id, Edit::Batch { label: "Detect form fields".into(), edits })?;
|
||||
Ok(names)
|
||||
|
||||
@@ -3722,6 +3722,28 @@ fn detecting_fields_on_a_printed_form() {
|
||||
assert!(s.detect_fields(id, &[]).is_empty(), "nothing left to detect");
|
||||
}
|
||||
|
||||
/// #294, #2831: a detected field sits on a line or box the page already draws, so it gets no border
|
||||
/// and no fill that would cover the printed form. A field drawn by hand keeps the defaults.
|
||||
#[test]
|
||||
fn detected_fields_have_no_border_or_fill() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
let id = s.open("paper.pdf", None, Arc::new(paper_form()), None).unwrap();
|
||||
let added = s.auto_detect_fields(id, &[]).unwrap();
|
||||
let d = s.get(id).unwrap();
|
||||
let kinds: Vec<pdfcraft_forms::FieldKind> = d.form.iter().map(|f| f.kind).collect();
|
||||
assert!(kinds.contains(&pdfcraft_forms::FieldKind::Text) && kinds.contains(&pdfcraft_forms::FieldKind::CheckBox), "{kinds:?}");
|
||||
for name in &added {
|
||||
let look = d.field_look(name).unwrap();
|
||||
assert_eq!((look.border, look.fill), (None, None), "{name}");
|
||||
}
|
||||
assert_eq!(d.can_undo(), Some("Detect form fields"), "still one step");
|
||||
|
||||
s.apply(id, Edit::AddField { page: 0, rect: [200.0, 10.0, 300.0, 30.0], kind: NewField::Text { multiline: false }, name: Some("drawn".into()) })
|
||||
.unwrap();
|
||||
let look = s.get(id).unwrap().field_look("drawn").unwrap();
|
||||
assert!(look.border.is_some() && look.fill.is_some(), "{look:?}");
|
||||
}
|
||||
|
||||
/// A printed form, 420 × 300 pt: a title, a label with a rule to write on, a box with a small
|
||||
/// label in its corner, an empty box with its label above, and two check boxes.
|
||||
fn paper_form() -> Vec<u8> {
|
||||
|
||||
@@ -5088,8 +5088,8 @@ milestone = "M6"
|
||||
status = "partial"
|
||||
commands = ["form.detect", "form.prepare"]
|
||||
tools = ["form_detect_fields"]
|
||||
evidence = ["crates/forms/src/tests.rs::detection_finds_blanks_rules_boxes_and_names_them", "crates/forms/src/tests.rs::page_shapes_reads_rectangles_with_points_along_their_sides", "crates/engine/src/tests.rs::detecting_fields_on_a_printed_form", "crates/forms/src/tests.rs::detection_makes_a_row_of_touching_cells_one_comb_field", "crates/engine/src/tests.rs::detecting_comb_boxes_adds_one_comb_field_per_row", "crates/engine/src/tests.rs::detecting_fields_on_a_scanned_form", "crates/forms/src/detect/raster.rs::a_scanned_form_gives_its_rules_boxes_and_check_boxes", "crates/forms/src/detect/raster.rs::noise_and_uneven_paper_do_not_hide_the_lines", "crates/automation/tests/automation.rs::detecting_form_fields_through_tools", "crates/automation/tests/automation.rs::detecting_comb_boxes_through_tools", "crates/ui-egui/tests/javascript.rs::prepare_a_form_detects_fields_on_a_paper_form", "crates/ui-egui/tests/prepare.rs::deleting_several_selected_fields_and_detecting_fields_from_the_panel"]
|
||||
notes = "Underscore runs, rules, empty boxes, small squares (check boxes) and rows of two or more touching cells of one size (one comb text field, character limit = cells; tested on drawn forms only); a box drawn with points along its sides (a midpoint on each vertical side, as the French 2042 form's cells) is read as the rectangle it is (#2942); runs when Prepare a form starts on a document without fields, and from Prepare a form ▸ Detect form fields at any time (existing fields are skipped). Scanned pages (an image covers at least half the page and the content draws no lines) are rendered and their rules, boxes and check boxes read from the pixels; a box with a small printed label gets a field in its empty part. Tested on synthetic scans only: straight, stored sideways with /Rotate 90 (fields get /MK /R so typing reads upright), noisy, and 1 degree askew (fields stay inside their boxes but lose up to the skew in height). Labels come from the text layer or, when the OCR models are installed, from text recognition (Latin without accents, so German labels with umlauts make poorer names); without either, fields get default names (Text1, Check Box1). Recognition runs synchronously, about a second per scanned page. Not yet: dotted leader lines, tables of cells as such, deskewing, radio groups."
|
||||
evidence = ["crates/forms/src/tests.rs::detection_finds_blanks_rules_boxes_and_names_them", "crates/forms/src/tests.rs::page_shapes_reads_rectangles_with_points_along_their_sides", "crates/engine/src/tests.rs::detecting_fields_on_a_printed_form", "crates/engine/src/tests.rs::detected_fields_have_no_border_or_fill", "crates/forms/src/tests.rs::detection_makes_a_row_of_touching_cells_one_comb_field", "crates/engine/src/tests.rs::detecting_comb_boxes_adds_one_comb_field_per_row", "crates/engine/src/tests.rs::detecting_fields_on_a_scanned_form", "crates/forms/src/detect/raster.rs::a_scanned_form_gives_its_rules_boxes_and_check_boxes", "crates/forms/src/detect/raster.rs::noise_and_uneven_paper_do_not_hide_the_lines", "crates/automation/tests/automation.rs::detecting_form_fields_through_tools", "crates/automation/tests/automation.rs::detecting_comb_boxes_through_tools", "crates/ui-egui/tests/javascript.rs::prepare_a_form_detects_fields_on_a_paper_form", "crates/ui-egui/tests/prepare.rs::deleting_several_selected_fields_and_detecting_fields_from_the_panel"]
|
||||
notes = "Underscore runs, rules, empty boxes, small squares (check boxes) and rows of two or more touching cells of one size (one comb text field, character limit = cells; tested on drawn forms only); a box drawn with points along its sides (a midpoint on each vertical side, as the French 2042 form's cells) is read as the rectangle it is (#2942); runs when Prepare a form starts on a document without fields, and from Prepare a form ▸ Detect form fields at any time (existing fields are skipped). Scanned pages (an image covers at least half the page and the content draws no lines) are rendered and their rules, boxes and check boxes read from the pixels; a box with a small printed label gets a field in its empty part. Detected fields get no border and no fill, since the page already draws the line or box they sit on; fields drawn by hand keep the grey border and white fill. Tested on synthetic scans only: straight, stored sideways with /Rotate 90 (fields get /MK /R so typing reads upright), noisy, and 1 degree askew (fields stay inside their boxes but lose up to the skew in height). Labels come from the text layer or, when the OCR models are installed, from text recognition (Latin without accents, so German labels with umlauts make poorer names); without either, fields get default names (Text1, Check Box1). Recognition runs synchronously, about a second per scanned page. Not yet: dotted leader lines, tables of cells as such, deskewing, radio groups."
|
||||
|
||||
[[feature]]
|
||||
id = "form.auto-name-fields"
|
||||
|
||||
Reference in New Issue
Block a user