diff --git a/Cargo.lock b/Cargo.lock index b174b4ae..b60e6002 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3642,7 +3642,6 @@ dependencies = [ "pdfcraft-cos", "pdfcraft-fonts", "pdfcraft-model", - "pdfcraft-render", "thiserror 2.0.21", ] diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 1e497399..6e195040 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2205,3 +2205,51 @@ fn comments_without_appearances_are_drawn_but_not_saved() { assert!(reopened.get(r).as_dict().is_some_and(|d| !d.contains(b"AP")), "{r:?} is saved without /AP"); } } + +/// Forms (L3) may not depend on render (L3), so this check of what a rotated field's appearance +/// draws lives here, where both are available. +#[test] +fn a_rotated_form_field_draws_along_the_vertical_edge() { + use pdfcraft_cos::{Document, Object, SaveOptions, write_incremental}; + use pdfcraft_forms::{FieldProps, FieldValue, NewField, add_field, set_props, set_value}; + use pdfcraft_render::{PageRenderer, RenderConfig, RenderRequest, RequestKind}; + let mut doc = Document::new_empty(); + let pages = doc.get(doc.root().unwrap()).as_dict().unwrap().reference(b"Pages").unwrap(); + let mut p = pdfcraft_cos::Dict::new(); + p.set(b"Type".to_vec(), Object::name("Page")); + p.set(b"Parent".to_vec(), Object::Ref(pages)); + p.set(b"MediaBox".to_vec(), Object::Array(vec![0.into(), 0.into(), 600.into(), 800.into()])); + let r = doc.add(p); + doc.update_dict(pages, |d| { + d.set(b"Kids".to_vec(), Object::Array(vec![Object::Ref(r)])); + d.set(b"Count".to_vec(), Object::Int(1)); + }) + .unwrap(); + add_field(&mut doc, 0, [10.0, 40.0, 90.0, 60.0], &NewField::Text { multiline: false }, Some("wide")).unwrap(); + set_value(&mut doc, "wide", &FieldValue::Text("MMMMMM".into())).unwrap(); + set_props(&mut doc, "wide", &FieldProps { font_size: Some(12.0), ..FieldProps::default() }).unwrap(); + let span = |doc: &Document| -> (u32, u32) { + let bytes = write_incremental(doc, &SaveOptions::default()).unwrap(); + let mut r = PageRenderer::new(Arc::new(bytes), RenderConfig::default()); + let p = r.render(RenderRequest { page: 0, kind: RequestKind::Pixels, tile: None, scale: 2.0, tag: 0 }); + assert!(p.error.is_none(), "{:?}", p.error); + let (mut x0, mut y0, mut x1, mut y1) = (u32::MAX, u32::MAX, 0, 0); + let mut ink = false; + for y in 0..p.height { + for x in 0..p.width { + let i = ((y * p.width + x) * 4) as usize; + if p.rgba[i] < 200 { + ink = true; + (x0, y0, x1, y1) = (x0.min(x), y0.min(y), x1.max(x), y1.max(y)); + } + } + } + assert!(ink, "the field drew no text"); + (x1 - x0, y1 - y0) + }; + let (wide, tall) = span(&doc); + assert!(wide > tall, "upright text is a horizontal run: {wide}x{tall}"); + set_props(&mut doc, "wide", &FieldProps { rotation: Some((0, 90)), ..FieldProps::default() }).unwrap(); + let (wide, tall) = span(&doc); + assert!(tall > wide, "rotated text is a vertical run: {wide}x{tall}"); +} diff --git a/crates/forms/Cargo.toml b/crates/forms/Cargo.toml index ce6a73a5..3f085ee6 100644 --- a/crates/forms/Cargo.toml +++ b/crates/forms/Cargo.toml @@ -17,4 +17,3 @@ thiserror = { workspace = true } [dev-dependencies] hayro-syntax = { workspace = true } -pdfcraft-render = { workspace = true } diff --git a/crates/forms/src/tests.rs b/crates/forms/src/tests.rs index 6d5317ad..af1a8529 100644 --- a/crates/forms/src/tests.rs +++ b/crates/forms/src/tests.rs @@ -1062,36 +1062,3 @@ fn a_rotation_refused_as_too_small_changes_nothing_else() { assert_eq!(f.tooltip, None, "the tooltip was written before the rotation was refused"); assert_eq!(f.widgets[0].rotation, 0); } - -#[test] -fn a_rotated_field_draws_along_the_vertical_edge() { - use pdfcraft_render::{PageRenderer, RenderConfig, RenderRequest, RequestKind}; - let mut doc = one_page(); - add_field(&mut doc, 0, [10.0, 40.0, 90.0, 60.0], &NewField::Text { multiline: false }, Some("wide")).unwrap(); - set_value(&mut doc, "wide", &FieldValue::Text("MMMMMM".into())).unwrap(); - set_props(&mut doc, "wide", &FieldProps { font_size: Some(12.0), ..FieldProps::default() }).unwrap(); - let span = |doc: &Document| -> (u32, u32) { - let bytes = write_incremental(doc, &SaveOptions::default()).unwrap(); - let mut r = PageRenderer::new(Arc::new(bytes), RenderConfig::default()); - let p = r.render(RenderRequest { page: 0, kind: RequestKind::Pixels, tile: None, scale: 2.0, tag: 0 }); - assert!(p.error.is_none(), "{:?}", p.error); - let (mut x0, mut y0, mut x1, mut y1) = (u32::MAX, u32::MAX, 0, 0); - let mut ink = false; - for y in 0..p.height { - for x in 0..p.width { - let i = ((y * p.width + x) * 4) as usize; - if p.rgba[i] < 200 { - ink = true; - (x0, y0, x1, y1) = (x0.min(x), y0.min(y), x1.max(x), y1.max(y)); - } - } - } - assert!(ink, "the field drew no text"); - (x1 - x0, y1 - y0) - }; - let (wide, tall) = span(&doc); - assert!(wide > tall, "upright text is a horizontal run: {wide}x{tall}"); - set_props(&mut doc, "wide", &FieldProps { rotation: Some((0, 90)), ..FieldProps::default() }).unwrap(); - let (wide, tall) = span(&doc); - assert!(tall > wide, "rotated text is a vertical run: {wide}x{tall}"); -} diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index 7a77624c..fe7fb156 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -4398,7 +4398,7 @@ milestone = "M6" status = "partial" commands = ["form.fields"] tools = ["form_fill", "form_set_props"] -evidence = ["crates/forms/src/tests.rs::text_fields_get_new_appearances", "crates/forms/src/tests.rs::choices_accept_exports_or_display_text", "crates/forms/src/tests.rs::rotated_fields_draw_in_their_quadrant", "crates/forms/src/tests.rs::a_rotated_field_draws_along_the_vertical_edge", "crates/automation/tests/automation.rs::rotating_a_field_through_tools", "crates/ui-egui/tests/prepare.rs::position_tab_rotates_a_field"] +evidence = ["crates/forms/src/tests.rs::text_fields_get_new_appearances", "crates/forms/src/tests.rs::choices_accept_exports_or_display_text", "crates/forms/src/tests.rs::rotated_fields_draw_in_their_quadrant", "crates/engine/src/tests.rs::a_rotated_form_field_draws_along_the_vertical_edge", "crates/automation/tests/automation.rs::rotating_a_field_through_tools", "crates/ui-egui/tests/prepare.rs::position_tab_rotates_a_field"] notes = "auto-size, comb, multiline, password, quadding, /MK colours and /MK /R rotation (0, 90, 180, 270); approximate Helvetica metrics" [[feature]]