mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 20:47:32 -06:00
M6: detect a row of comb boxes as one comb text field (#2111)
* M6: detect a row of comb boxes as one comb text field (fixes #1887) * M6: keep empty tables of wide cells out of comb detection (#1887) --------- Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Brandon Thomas
parent
eeadc79d15
commit
50f261d70c
+18
-13
@@ -6,7 +6,7 @@
|
||||
//! Preferences ▸ JavaScript ▸ Enable Acrobat JavaScript is [`Session::set_javascript`]; with it
|
||||
//! off, scripts don't run and AF calls keep working natively.
|
||||
|
||||
use pdfcraft_forms::{Field, FieldChange, FieldEvent, FieldKind, ScriptResult, Scripts};
|
||||
use pdfcraft_forms::{Field, FieldChange, FieldEvent, FieldKind, FieldProps, ScriptResult, Scripts};
|
||||
pub use pdfcraft_js::{Limits, Outcome, Request};
|
||||
|
||||
use crate::{DocId, Edit, EditError, Session};
|
||||
@@ -343,19 +343,24 @@ impl Session {
|
||||
let names = found.iter().map(|(_, c, _)| c.name.clone()).collect();
|
||||
let mut edits = Vec::with_capacity(found.len());
|
||||
for (page, c, turn) in found {
|
||||
// A turned field keeps its place: the rectangle is already the one on the page.
|
||||
let props = (turn != 0).then(|| pdfcraft_forms::FieldProps { rotation: Some((0, turn)), rect: Some((0, c.rect)), ..Default::default() });
|
||||
let tall = if turn % 180 == 0 { c.rect[3] - c.rect[1] } else { c.rect[2] - c.rect[0] };
|
||||
edits.push(Edit::AddField {
|
||||
page,
|
||||
rect: c.rect,
|
||||
kind: match c.kind {
|
||||
pdfcraft_forms::detect::Kind::Text => pdfcraft_forms::NewField::Text { multiline: tall > 30.0 },
|
||||
pdfcraft_forms::detect::Kind::CheckBox => pdfcraft_forms::NewField::CheckBox,
|
||||
},
|
||||
name: Some(c.name.clone()),
|
||||
});
|
||||
if let Some(props) = props {
|
||||
let (kind, comb) = match c.kind {
|
||||
pdfcraft_forms::detect::Kind::Text => (pdfcraft_forms::NewField::Text { multiline: tall > 30.0 }, None),
|
||||
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();
|
||||
if turn != 0 {
|
||||
// A turned field keeps its place: the rectangle is already the one on the page.
|
||||
props.rotation = Some((0, turn));
|
||||
props.rect = Some((0, c.rect));
|
||||
}
|
||||
if let Some(cells) = comb {
|
||||
props.max_len = Some(Some(cells));
|
||||
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) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3691,6 +3691,34 @@ fn detecting_fields_on_a_scanned_form() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detecting_comb_boxes_adds_one_comb_field_per_row() {
|
||||
// The rows from #1887: five 18 x 22 cells and ten 16 x 20 cells, each a stroked `re`.
|
||||
let mut body = String::from("BT /F1 10 Tf 40 205 Td (Postcode A) Tj ET BT /F1 10 Tf 40 105 Td (Postcode B) Tj ET\n");
|
||||
for i in 0..5 {
|
||||
body.push_str(&format!("{} 200 18 22 re S\n", 120 + i * 18));
|
||||
}
|
||||
for i in 0..10 {
|
||||
body.push_str(&format!("{} 100 16 20 re S\n", 120 + i * 16));
|
||||
}
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
let id = s.open("comb.pdf", None, Arc::new(one_line_page("/Font << /F1 4 0 R >>", &body)), None).unwrap();
|
||||
let found: Vec<(String, pdfcraft_forms::detect::Kind)> = s.detect_fields(id, &[]).into_iter().map(|(_, c)| (c.name, c.kind)).collect();
|
||||
assert_eq!(
|
||||
found,
|
||||
[
|
||||
("Postcode A".to_string(), pdfcraft_forms::detect::Kind::Comb { cells: 5 }),
|
||||
("Postcode B".to_string(), pdfcraft_forms::detect::Kind::Comb { cells: 10 })
|
||||
]
|
||||
);
|
||||
s.auto_detect_fields(id, &[]).unwrap();
|
||||
let d = s.get(id).unwrap();
|
||||
let combs: Vec<(&str, FormFieldKind, bool, Option<usize>)> =
|
||||
d.form.iter().map(|f| (f.name.as_str(), f.kind, f.has(pdfcraft_forms::flags::COMB), f.max_len)).collect();
|
||||
assert_eq!(combs, [("Postcode A", FormFieldKind::Text, true, Some(5)), ("Postcode B", FormFieldKind::Text, true, Some(10))]);
|
||||
assert_eq!(d.can_undo(), Some("Detect form fields"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comparing_two_versions_of_a_document() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
|
||||
Reference in New Issue
Block a user