Files
cadcraft/crates/io/tests/it/mtext_embedded_object.rs
aiongg 9cf115e808 CI: one test binary per crate, nextest, line tables only (#1989)
* Build: line tables only in dev, no debug info for dependencies

* Tests: one integration-test binary per crate

Each crate's tests/*.rs becomes a module of tests/it/main.rs. Files that
install process-wide state (the file io hooks, user aliases, SAVETIME and
SAVEFILEPATH, user linetype and pattern files, registered fonts) stay their
own test binaries.

* xtask ci: nextest, tests without examples, one wasm check call
2026-10-23 13:34:26 -04:00

80 lines
2.6 KiB
Rust

//! An R2018+ MTEXT can carry an embedded object (group 101) that repeats its geometry with
//! other meanings: there, 10 is the X-axis direction and 11 the insertion point. AutoCAD writes
//! one for MTEXT with column settings, and the DWG bridge does too. Reading 11 from it as the
//! direction turned the text towards its own insertion point (#667).
use cadcraft_doc::{Common, Drawing, EntityKind, MText, Space};
use cadcraft_geom::Vec3;
use cadcraft_io::{read_dxf, write_dxf};
/// An MTEXT at (30, 17) with `rotation`, written by CADCraft, then given an embedded object
/// as AutoCAD writes it: direction `dir` in 10/20/30 and the insertion point in 11/21/31.
fn with_embedded_object(rotation: f64, dir: (f64, f64)) -> String {
let mut d = Drawing::new_metric();
let t = MText {
insert: Vec3::new(30.0, 17.0, 0.0),
height: 0.5,
width: 6.0,
attach: 1,
rotation,
style: "Standard".into(),
contents: "Core Layer\\PThickness 1mm".into(),
line_spacing: 1.0,
line_spacing_exact: false,
columns: None,
};
d.add(&Space::Model, Common::default(), EntityKind::MText(t)).unwrap();
let dxf = write_dxf(&d);
let (dx, dy) = (dir.0.to_string(), dir.1.to_string());
let groups = [
(101, "Embedded Object"),
(70, "1"),
(10, &dx),
(20, &dy),
(30, "0.0"),
(11, "30.0"),
(21, "17.0"),
(31, "0.0"),
(40, "6.0"),
(41, "0.0"),
(42, "5.0"),
(43, "1.0"),
(71, "2"),
(72, "1"),
(44, "6.0"),
(45, "0.5"),
(73, "0"),
(74, "0"),
(46, "0.0"),
];
let embedded: String = groups.iter().map(|(code, value)| format!("{code:>3}\r\n{value}\r\n")).collect();
let start = dxf.find("AcDbMText").unwrap();
let end = start + dxf[start..].find("\r\n 0\r\n").unwrap() + 2;
format!("{}{embedded}{}", &dxf[..end], &dxf[end..])
}
fn read_rotation(dxf: &str) -> f64 {
let back = read_dxf(dxf.as_bytes()).unwrap();
match back.model.iter().find_map(|e| match &e.kind {
EntityKind::MText(t) => Some(t.rotation),
_ => None,
}) {
Some(r) => r,
None => panic!("no mtext"),
}
}
#[test]
fn embedded_object_insertion_point_is_not_the_direction() {
let dxf = with_embedded_object(0.0, (1.0, 0.0));
assert!(dxf.contains("Embedded Object"));
assert_eq!(read_rotation(&dxf), 0.0);
}
#[test]
fn rotated_mtext_keeps_its_rotation_with_an_embedded_object() {
let r = 0.5_f64;
let dxf = with_embedded_object(r, (r.cos(), r.sin()));
assert!((read_rotation(&dxf) - r).abs() < 1e-9);
}