From 03101e8d77b49a4c847f182dd8c98c0cbaca0b25 Mon Sep 17 00:00:00 2001 From: Rahul Date: Tue, 3 Nov 2026 03:31:26 +0530 Subject: [PATCH] fix(io): a moved DIMENSION draws its block at its insertion point (group 12) (#2634) (#2636) A DIMENSION moved by an older AutoCAD keeps its *D block contents where they were and the move in DXF group 12, and is drawn translated by the insertion point. Group 12 was never read into Dimension, so the block rendered at its pre-move position and the extents reached there too. Read group 12 into a new Dimension::insertion_point, draw the block translated by it, move its bounds with it in the extents, test the block's text where it draws, and write group 12 back whenever the block written is the one read from the file. Regenerated geometry (edits drop the block link) sits at its definition points, so no offset is kept or written for it. Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> --- crates/doc/src/entity/dim.rs | 5 +++ crates/doc/src/extents.rs | 4 ++ crates/doc/src/tests.rs | 39 +++++++++++++++++ crates/engine/src/cmd/annotate/common.rs | 1 + crates/engine/src/sample.rs | 3 ++ crates/engine/src/select.rs | 14 ++++--- crates/engine/tests/compare.rs | 1 + crates/engine/tests/it/compare_export.rs | 4 ++ crates/io/src/dxf_read/entities.rs | 1 + crates/io/src/dxf_write/entity.rs | 6 +++ crates/io/src/tests.rs | 2 + crates/io/tests/dimassoc_angular_radial.rs | 1 + crates/io/tests/it/acad_interop.rs | 1 + .../io/tests/it/dim_block_resave_roundtrip.rs | 42 +++++++++++++++++++ crates/io/tests/it/dim_block_text.rs | 2 + crates/io/tests/it/dim_marks_roundtrip.rs | 1 + crates/io/tests/it/dimstyle_vars_roundtrip.rs | 1 + crates/io/tests/it/dimtfill_roundtrip.rs | 1 + crates/io/tests/it/roundtrip/cases/complex.rs | 1 + crates/io/tests/it/roundtrip_audit.rs | 1 + crates/io/tests/it/text_carets_roundtrip.rs | 1 + crates/render/src/dim/tests.rs | 1 + crates/render/src/draw.rs | 9 +++- crates/render/src/tests.rs | 1 + crates/render/tests/it/dim_angular_centre.rs | 1 + crates/render/tests/it/dim_post_tolerance.rs | 1 + crates/render/tests/it/dim_text_fill.rs | 1 + crates/render/tests/it/dim_text_format.rs | 1 + crates/render/tests/it/render_props.rs | 1 + 29 files changed, 142 insertions(+), 6 deletions(-) diff --git a/crates/doc/src/entity/dim.rs b/crates/doc/src/entity/dim.rs index d10237b26..dc4635c7a 100644 --- a/crates/doc/src/entity/dim.rs +++ b/crates/doc/src/entity/dim.rs @@ -52,6 +52,11 @@ pub struct Dimension { /// Anonymous block with the rendered geometry (from files); regenerated when edited. #[serde(default)] pub block: Option, + /// Insertion point (DXF group 12): a dimension moved by an older AutoCAD keeps its offset + /// here with the `*D` block's contents left where they were, and is drawn translated by it. + /// Zero once the geometry is regenerated from the definition points. + #[serde(default)] + pub insertion_point: Vec3, /// Per-dimension style overrides (DIMOVERRIDE): DimStyle field names (camelCase) → values, /// merged over the named style. #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")] diff --git a/crates/doc/src/extents.rs b/crates/doc/src/extents.rs index 353a42b53..d87cdc9a2 100644 --- a/crates/doc/src/extents.rs +++ b/crates/doc/src/extents.rs @@ -212,6 +212,10 @@ fn bounds_in<'a>(d: &'a Drawing, e: &Entity, depth: usize, blocks: &mut HashMap< inner } }; + // The block draws translated by the insertion point (group 12), so its bounds + // move with it (#2634); the cache above keeps the block's own bounds. + let off = dm.insertion_point.xy(); + let inner = if off == Vec2::ZERO { inner } else { Bounds2 { min: inner.min + off, max: inner.max + off } }; b = b.union(&inner); } b diff --git a/crates/doc/src/tests.rs b/crates/doc/src/tests.rs index f0f979f12..29d55e30f 100644 --- a/crates/doc/src/tests.rs +++ b/crates/doc/src/tests.rs @@ -55,6 +55,44 @@ fn frozen_layers_are_left_out_of_extents_and_layers_turned_off_are_not() { assert_eq!(d.extents(&Space::Model).max, Vec2::new(1.0, 1.0)); } +/// DXF group 12: a dimension moved by an older AutoCAD keeps its `*D` block where it was and +/// the move in the insertion point, and the block draws translated by it. Extents follow the +/// drawing, not the stale block contents (#2634). +#[test] +fn dimension_insertion_point_moves_its_block_in_extents() { + let moved = |ins: Vec3| { + let mut d = Drawing::new_metric(); + let mut blk = Block::new("*D1"); + blk.entities.push(on_layer("0", line((850.0, 920.0), (860.0, 920.0)), 2)); + d.blocks.insert("*D1".into(), std::sync::Arc::new(blk)); + let dm = Dimension { + kind: DimKind::Aligned, + defpt: Vec3::new(5.0, 1.0, 0.0), + text_mid: Vec3::ZERO, + p13: Vec3::ZERO, + p14: Vec3::new(10.0, 0.0, 0.0), + p15: Vec3::ZERO, + p16: Vec3::ZERO, + text: String::new(), + style: "Standard".into(), + measurement: 0.0, + text_rotation: 0.0, + user_text_pos: false, + block: Some("*D1".into()), + insertion_point: ins, + overrides: Default::default(), + assoc: Vec::new(), + marks: Default::default(), + }; + d.add(&Space::Model, Common::default(), EntityKind::Dimension(dm)).unwrap(); + d + }; + // Without the offset the block's far-away contents reach the extents. + assert!(moved(Vec3::ZERO).extents(&Space::Model).max.x > 800.0); + // With it, the block draws at the definition points and the extents stay at the drawing. + assert!(moved(Vec3::new(-850.0, -920.0, 0.0)).extents(&Space::Model).max.x < 20.0); +} + /// ZOOM Extents in AutoCAD 2024 (accoreconsole, EXTMIN/EXTMAX read back; AutoCAD pads them by a /// few hundredths): a layer turned off counts and a frozen one does not, for an entity, for an /// entity inside a block, and for a block reference itself. @@ -637,6 +675,7 @@ fn invisible_dimblock_entity_is_ignored_in_dimension_extents() { overrides: Default::default(), assoc: vec![], marks: Default::default(), + insertion_point: Vec3::ZERO, }), ) .unwrap(); diff --git a/crates/engine/src/cmd/annotate/common.rs b/crates/engine/src/cmd/annotate/common.rs index 398102797..6854b4fb4 100644 --- a/crates/engine/src/cmd/annotate/common.rs +++ b/crates/engine/src/cmd/annotate/common.rs @@ -22,6 +22,7 @@ pub(super) fn dim(s: &Session, kind: DimKind, defpt: Vec2, p13: Vec2, p14: Vec2, overrides: s.doc().map(|d| d.dim_overrides()).unwrap_or_default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }) } diff --git a/crates/engine/src/sample.rs b/crates/engine/src/sample.rs index 85a222f64..4e615a4f2 100644 --- a/crates/engine/src/sample.rs +++ b/crates/engine/src/sample.rs @@ -32,6 +32,7 @@ fn dim(kind: DimKind, p13: Vec2, p14: Vec2, defpt: Vec2) -> EntityKind { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }) } @@ -182,6 +183,7 @@ pub fn bracket() -> Drawing { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }), ); add( @@ -203,6 +205,7 @@ pub fn bracket() -> Drawing { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }), ); diff --git a/crates/engine/src/select.rs b/crates/engine/src/select.rs index 8047412fd..6721cdad8 100644 --- a/crates/engine/src/select.rs +++ b/crates/engine/src/select.rs @@ -117,11 +117,15 @@ fn in_text(d: &Drawing, e: &Entity, p: Vec2) -> bool { // A dimension with a block (as AutoCAD saves them) is drawn from that block: its text is // the text there, not the text the dimension's own geometry would place. EntityKind::Dimension(dm) => match dm.block.as_ref().and_then(|n| d.block(n)) { - Some(blk) => blk.entities.iter().any(|be| match &be.kind { - EntityKind::MText(t) => in_box(cadcraft_render::layout_mtext_entity(d, t).strokes.into_iter().flatten(), t.rotation, p), - EntityKind::Text(_) => entity_bounds(d, be, 0).contains(p), - _ => false, - }), + // The block draws translated by the insertion point (group 12): test there (#2634). + Some(blk) => { + let p = p - dm.insertion_point.xy(); + blk.entities.iter().any(|be| match &be.kind { + EntityKind::MText(t) => in_box(cadcraft_render::layout_mtext_entity(d, t).strokes.into_iter().flatten(), t.rotation, p), + EntityKind::Text(_) => entity_bounds(d, be, 0).contains(p), + _ => false, + }) + } None => { let g = cadcraft_render::dimension_in(d, dm); in_box(g.text.iter().flatten().chain(g.text_glyphs.iter().flatten().flatten()).copied(), g.text_angle, p) diff --git a/crates/engine/tests/compare.rs b/crates/engine/tests/compare.rs index 0e4486ccb..a346fbba2 100644 --- a/crates/engine/tests/compare.rs +++ b/crates/engine/tests/compare.rs @@ -208,6 +208,7 @@ fn derived_dimension_fields_are_not_differences() { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; let mut s = Session::new(); s.doc_mut().unwrap().add(&Space::Model, Common::default(), EntityKind::Dimension(dim(30.0, 7.0))).unwrap(); diff --git a/crates/engine/tests/it/compare_export.rs b/crates/engine/tests/it/compare_export.rs index 1aee1b9db..740133c2b 100644 --- a/crates/engine/tests/it/compare_export.rs +++ b/crates/engine/tests/it/compare_export.rs @@ -314,6 +314,7 @@ fn a_named_block_whose_dimension_draws_another_block_shows_the_other_definition( overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; let blocks = |dim_end: f64, first: u64| { let mut part = Block::new("PART"); @@ -400,6 +401,7 @@ fn a_named_block_whose_dimension_block_has_another_generated_name_keeps_this_dra overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; let mut part = Block::new("PART"); part.entities.push(Entity::new(Handle(first), EntityKind::Dimension(dim))); @@ -514,6 +516,7 @@ fn a_dimension_block_copy_keeps_its_geometry_when_the_snapshot_is_saved() { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; let mut s = Session::new(); let mut drawn = Block::new("*D1"); @@ -833,6 +836,7 @@ fn a_dimension_whose_block_is_past_the_nesting_limit_is_drawn_again() { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; for k in 1..=MAX_BLOCK_DEPTH { let mut b = Block::new(&format!("B{k}")); diff --git a/crates/io/src/dxf_read/entities.rs b/crates/io/src/dxf_read/entities.rs index 2011c3d63..6ca0f30d1 100644 --- a/crates/io/src/dxf_read/entities.rs +++ b/crates/io/src/dxf_read/entities.rs @@ -197,6 +197,7 @@ pub(super) fn entity_with_table_budget(kind: &str, tags: &[Tag], table_cells_lef text_rotation: t.fd(53, 0.0).to_radians(), user_text_pos: t.i(70).unwrap_or(0) & 128 != 0, block: t.s(2).filter(|s| !s.is_empty()), + insertion_point: t.p(12), overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), diff --git a/crates/io/src/dxf_write/entity.rs b/crates/io/src/dxf_write/entity.rs index 51b6b4388..ee9c18d33 100644 --- a/crates/io/src/dxf_write/entity.rs +++ b/crates/io/src/dxf_write/entity.rs @@ -399,6 +399,12 @@ fn write_dimension_entity(w: &mut W, d: &Drawing, e: &Entity, owner: &str, paper let style = d.dim_style(&dm.style).cloned().unwrap_or_default(); let g = cadcraft_render::dimension_geometry(dm, &style, d.header.f64("DIMSCALE", 1.0)); w.p(11, if dm.user_text_pos { dm.text_mid } else { g.text_pos.to3(0.0) }); + // Group 12: a block read from a file keeps the dimension's moved-by offset (AutoCAD + // draws the block translated by it); regenerated geometry already sits where the + // definition points place it, so it writes no offset. + if dm.block.is_some() && dm.insertion_point != Vec3::ZERO { + w.p(12, dm.insertion_point); + } let ty: i64 = match dm.kind { DimKind::Linear { .. } => 0, DimKind::Aligned => 1, diff --git a/crates/io/src/tests.rs b/crates/io/src/tests.rs index 4aa427bdd..5d08817c5 100644 --- a/crates/io/src/tests.rs +++ b/crates/io/src/tests.rs @@ -98,6 +98,7 @@ fn sample() -> Drawing { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }), ) .unwrap(); @@ -558,6 +559,7 @@ fn dim(kind: DimKind, p13: Vec3, p14: Vec3) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/io/tests/dimassoc_angular_radial.rs b/crates/io/tests/dimassoc_angular_radial.rs index f955ad7b5..1df635320 100644 --- a/crates/io/tests/dimassoc_angular_radial.rs +++ b/crates/io/tests/dimassoc_angular_radial.rs @@ -27,6 +27,7 @@ fn dim(kind: DimKind, defpt: Vec3, p13: Vec3, p14: Vec3, p15: Vec3, p16: Vec3, a overrides: Default::default(), assoc, marks: Default::default(), + insertion_point: Vec3::ZERO, }) } diff --git a/crates/io/tests/it/acad_interop.rs b/crates/io/tests/it/acad_interop.rs index 387f23334..bc9cc90e1 100644 --- a/crates/io/tests/it/acad_interop.rs +++ b/crates/io/tests/it/acad_interop.rs @@ -98,6 +98,7 @@ fn s25(kind: DimKind, p13: Vec3, p14: Vec3, defpt: Vec3) -> Drawing { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; d.add(&Space::Model, Common::default(), EntityKind::Dimension(dm)).unwrap(); d diff --git a/crates/io/tests/it/dim_block_resave_roundtrip.rs b/crates/io/tests/it/dim_block_resave_roundtrip.rs index f0705d6fd..195706157 100644 --- a/crates/io/tests/it/dim_block_resave_roundtrip.rs +++ b/crates/io/tests/it/dim_block_resave_roundtrip.rs @@ -27,6 +27,7 @@ fn linear(a: [f64; 2], b: [f64; 2], at: [f64; 2]) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } @@ -158,6 +159,47 @@ fn reopened_dimension_reuses_its_block_name_and_handles() { assert_eq!(again.handseed, back.handseed); } +#[test] +fn a_moved_dimension_keeps_its_group_12_offset() { + let mut d = Drawing::new_metric(); + // What an older AutoCAD left: the block contents where the dimension was measured, the + // move kept in group 12 (insertion point), as #2634's drawing has it. + let mut b = Block::new("*D3"); + let h = d.new_handle(); + b.entities.push(Entity::new(h, EntityKind::Line(Line { a: Vec3::new(150.0, 80.0, 0.0), b: Vec3::new(160.0, 80.0, 0.0) }))); + d.blocks.insert("*D3".into(), Arc::new(b)); + let mut dm = linear([0.0, 0.0], [10.0, 0.0], [5.0, 3.0]); + dm.block = Some("*D3".into()); + dm.insertion_point = Vec3::new(-150.0, -80.0, 0.0); + let h = d.add(&Space::Model, Common::default(), EntityKind::Dimension(dm)).unwrap(); + + // The block is written as read and the offset round-trips as group 12. + let back = cadcraft_io::read_dxf(cadcraft_io::write_dxf(&d).as_bytes()).unwrap(); + let Some(EntityKind::Dimension(dm)) = back.entity(h).map(|e| &e.kind) else { panic!("dimension lost") }; + assert_eq!(dm.insertion_point, Vec3::new(-150.0, -80.0, 0.0)); + assert_eq!(dm.block.as_deref(), Some("*D3")); + let p = pairs(&cadcraft_io::write_dxf(&d)); + let at = p.iter().position(|(c, v)| *c == 0 && v == "DIMENSION").unwrap(); + let own = &p[at..p[at + 1..].iter().position(|(c, _)| *c == 0).map(|k| at + 1 + k).unwrap()]; + assert!(own.iter().any(|(c, v)| *c == 12 && v.parse::() == Ok(-150.0)), "no group 12 x"); + assert!(own.iter().any(|(c, v)| *c == 22 && v.parse::() == Ok(-80.0)), "no group 12 y"); + + // Edited (edits drop the block link): geometry regenerated from the definition points, + // so the save writes no offset. + let mut edited = back.clone(); + edited + .modify_entity(h, |e| { + if let EntityKind::Dimension(dm) = &mut e.kind { + dm.block = None; + } + }) + .unwrap(); + let q = pairs(&cadcraft_io::write_dxf(&edited)); + let at = q.iter().position(|(c, v)| *c == 0 && v == "DIMENSION").unwrap(); + let own = &q[at..q[at + 1..].iter().position(|(c, _)| *c == 0).map(|k| at + 1 + k).unwrap()]; + assert!(!own.iter().any(|(c, _)| *c == 12), "regenerated geometry keeps a stale offset"); +} + #[test] fn hostile_handle_seed_does_not_panic() { let mut d = Drawing::new_metric(); diff --git a/crates/io/tests/it/dim_block_text.rs b/crates/io/tests/it/dim_block_text.rs index 0c5fa0cab..244e9401c 100644 --- a/crates/io/tests/it/dim_block_text.rs +++ b/crates/io/tests/it/dim_block_text.rs @@ -34,6 +34,7 @@ fn height_written(style_scale: f64, overrides: serde_json::Value) -> f64 { overrides: overrides.as_object().cloned().unwrap_or_default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; d.add(&Space::Model, Common::default(), EntityKind::Dimension(dm)).unwrap(); block_mtext_height(&cadcraft_io::write_dxf(&d)) @@ -73,6 +74,7 @@ fn angular_drawing(separator_override: Option<&str>) -> Drawing { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; if let Some(separator) = separator_override { dm.overrides.insert("DIMDSEP".into(), serde_json::json!(separator)); diff --git a/crates/io/tests/it/dim_marks_roundtrip.rs b/crates/io/tests/it/dim_marks_roundtrip.rs index 40a85d89a..c442376de 100644 --- a/crates/io/tests/it/dim_marks_roundtrip.rs +++ b/crates/io/tests/it/dim_marks_roundtrip.rs @@ -24,6 +24,7 @@ fn dim(kind: DimKind, marks: DimMarks) -> EntityKind { overrides: Default::default(), assoc: Vec::new(), marks, + insertion_point: Vec3::ZERO, }) } diff --git a/crates/io/tests/it/dimstyle_vars_roundtrip.rs b/crates/io/tests/it/dimstyle_vars_roundtrip.rs index 061054bbc..b2beac3e2 100644 --- a/crates/io/tests/it/dimstyle_vars_roundtrip.rs +++ b/crates/io/tests/it/dimstyle_vars_roundtrip.rs @@ -60,6 +60,7 @@ fn dimension(overrides: serde_json::Value) -> EntityKind { overrides: overrides.as_object().cloned().unwrap_or_default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }) } diff --git a/crates/io/tests/it/dimtfill_roundtrip.rs b/crates/io/tests/it/dimtfill_roundtrip.rs index 5e1b4f1bf..48f7d9e32 100644 --- a/crates/io/tests/it/dimtfill_roundtrip.rs +++ b/crates/io/tests/it/dimtfill_roundtrip.rs @@ -174,6 +174,7 @@ fn linear() -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/io/tests/it/roundtrip/cases/complex.rs b/crates/io/tests/it/roundtrip/cases/complex.rs index ab13f4800..163effa49 100644 --- a/crates/io/tests/it/roundtrip/cases/complex.rs +++ b/crates/io/tests/it/roundtrip/cases/complex.rs @@ -118,6 +118,7 @@ pub(crate) fn dimensions() -> Vec { overrides: Default::default(), assoc: Vec::new(), marks: DimMarks::default(), + insertion_point: Vec3::ZERO, }), ); let mut block = Block::new("*D42"); diff --git a/crates/io/tests/it/roundtrip_audit.rs b/crates/io/tests/it/roundtrip_audit.rs index c2a326935..57f99dbe2 100644 --- a/crates/io/tests/it/roundtrip_audit.rs +++ b/crates/io/tests/it/roundtrip_audit.rs @@ -1034,6 +1034,7 @@ fn add_associated_dimension(d: &mut Drawing, a: cadcraft_doc::Handle, b: cadcraf overrides: Default::default(), assoc: vec![at("p13", a), at("p14", b)], marks: Default::default(), + insertion_point: Vec3::ZERO, }; d.add(&Space::Model, Common::default(), EntityKind::Dimension(dm)).expect("add dimension"); } diff --git a/crates/io/tests/it/text_carets_roundtrip.rs b/crates/io/tests/it/text_carets_roundtrip.rs index 1c30dd1a3..d327c6694 100644 --- a/crates/io/tests/it/text_carets_roundtrip.rs +++ b/crates/io/tests/it/text_carets_roundtrip.rs @@ -38,6 +38,7 @@ fn dimension(label: &str) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/src/dim/tests.rs b/crates/render/src/dim/tests.rs index fe3b3c74e..15001c6b7 100644 --- a/crates/render/src/dim/tests.rs +++ b/crates/render/src/dim/tests.rs @@ -19,6 +19,7 @@ fn lin(p1: (f64, f64), p2: (f64, f64), on: (f64, f64), rot: f64) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/src/draw.rs b/crates/render/src/draw.rs index 39b0ddfcc..e73659675 100644 --- a/crates/render/src/draw.rs +++ b/crates/render/src/draw.rs @@ -313,7 +313,10 @@ fn draw_dimension(b: &mut Builder, ctx: &Ctx, e: &Entity, dm: &cadcraft_doc::Dim if let Some(blk) = dm.block.as_ref().and_then(|n| ctx.d.block(n)) && ctx.depth < cadcraft_doc::MAX_BLOCK_DEPTH { - let sub = Ctx { block_pstyle: b.named, block_transparency: b.transparency, ..sub_ctx(ctx, e, Mat3::IDENTITY) }; + // DXF group 12: a moved dimension keeps its `*D` block where it was and the offset in + // the insertion point, so the block draws translated by it (#2634). + let off = dm.insertion_point.xy(); + let sub = Ctx { block_pstyle: b.named, block_transparency: b.transparency, ..sub_ctx(ctx, e, Mat3::translate(off)) }; // DIMTFILL: the block's MTEXT carries no background mask here, so a background // around each of the block's texts is drawn before the block's first text or first // line of the text's marks, except for a text that a SOLID of the block covers. @@ -333,6 +336,10 @@ fn draw_dimension(b: &mut Builder, ctx: &Ctx, e: &Entity, dm: &cadcraft_doc::Dim .take(MAX_FILL_TEXTS) .filter(|be| !covered(be)) .filter_map(|be| block_text_box(ctx.d, be, gap)) + .map(|mut corners| { + corners.iter_mut().for_each(|c| *c += off); + corners + }) .collect() }; let mut fill_pending = !boxes.is_empty(); diff --git a/crates/render/src/tests.rs b/crates/render/src/tests.rs index fe2dc6470..e4b314ff5 100644 --- a/crates/render/src/tests.rs +++ b/crates/render/src/tests.rs @@ -370,6 +370,7 @@ fn lin_dim() -> cadcraft_doc::Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/tests/it/dim_angular_centre.rs b/crates/render/tests/it/dim_angular_centre.rs index 9e9c42bdc..149638e0c 100644 --- a/crates/render/tests/it/dim_angular_centre.rs +++ b/crates/render/tests/it/dim_angular_centre.rs @@ -23,6 +23,7 @@ fn dim(kind: DimKind) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/tests/it/dim_post_tolerance.rs b/crates/render/tests/it/dim_post_tolerance.rs index 907271a7c..83177d6ec 100644 --- a/crates/render/tests/it/dim_post_tolerance.rs +++ b/crates/render/tests/it/dim_post_tolerance.rs @@ -22,6 +22,7 @@ fn text(vars: serde_json::Value) -> (String, String) { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; let mut st = DimStyle::default(); let rejected = st.apply_fields(vars.as_object().unwrap()); diff --git a/crates/render/tests/it/dim_text_fill.rs b/crates/render/tests/it/dim_text_fill.rs index b90e1595d..46028a576 100644 --- a/crates/render/tests/it/dim_text_fill.rs +++ b/crates/render/tests/it/dim_text_fill.rs @@ -26,6 +26,7 @@ fn dimension() -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/tests/it/dim_text_format.rs b/crates/render/tests/it/dim_text_format.rs index e70deea08..779667e5b 100644 --- a/crates/render/tests/it/dim_text_format.rs +++ b/crates/render/tests/it/dim_text_format.rs @@ -23,6 +23,7 @@ fn linear(len: f64) -> Dimension { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, } } diff --git a/crates/render/tests/it/render_props.rs b/crates/render/tests/it/render_props.rs index f210dc4e1..a40b1988d 100644 --- a/crates/render/tests/it/render_props.rs +++ b/crates/render/tests/it/render_props.rs @@ -47,6 +47,7 @@ fn dimensions_take_the_viewport_layer_colour() { overrides: Default::default(), assoc: Vec::new(), marks: Default::default(), + insertion_point: Vec3::ZERO, }; d.add(&Space::Model, on("A"), EntityKind::Dimension(dim)).unwrap(); d.add(&Space::Model, on("A"), EntityKind::Line(Line { a: Vec3::new(0.0, -1.0, 0.0), b: Vec3::new(10.0, -1.0, 0.0) })).unwrap();