Keep viewport frozen-layer lists through DXF save and reopen (#98) (#150)

This commit is contained in:
MarekSpodBiedry authored and GitHub committed 2026-10-10 12:14:21 -04:00
1 parent 576e6f9020
commit b7f83a6687
4 files changed
+52 -1

No files matched your search

+14
View File
@@ -306,6 +306,20 @@ pub(crate) fn assoc_xdata(assoc: &[DimAssoc]) -> Vec<Tag> {
v
}
/// A viewport's frozen layer names as CADCraft xdata: `1000 VPFROZEN`, `1002 {`, one `1000` per layer, `1002 }`.
pub(crate) fn frozen_xdata(layers: &[String]) -> Vec<Tag> {
let mut v = vec![Tag::s(1000, "VPFROZEN"), Tag::s(1002, "{")];
v.extend(layers.iter().map(|l| Tag::s(1000, l.clone())));
v.push(Tag::s(1002, "}"));
v
}
/// The frozen layer names written by [`frozen_xdata`]; empty for files from other writers.
pub(crate) fn read_frozen(tags: &[Tag]) -> Vec<String> {
let list = xdata_list(xdata(tags, APP), "VPFROZEN");
list.iter().take(MAX_XDATA_ITEMS).filter(|t| t.code == 1000).map(Tag::str).collect()
}
const POINT_NAMES: [&str; 5] = ["defpt", "p13", "p14", "p15", "p16"];
/// Associativity links from CADCraft xdata; malformed links are skipped.
+1 -1
View File
@@ -288,7 +288,7 @@ fn entity(kind: &str, tags: &[Tag]) -> Option<(Common, EntityKind)> {
view_height: t.fd(45, 1.0),
id: t.i(69).unwrap_or(0) as u32,
locked: t.i(90).unwrap_or(0) & 16384 != 0,
frozen_layers: Vec::new(),
frozen_layers: crate::dxf_ext::read_frozen(tags),
layer_colors: Vec::new(),
}),
"WIPEOUT" => {
+4
View File
@@ -765,6 +765,10 @@ fn entity(w: &mut W, d: &Drawing, e: &Entity, owner: &str, paper: bool, cx: &Ctx
w.f(45, v.view_height);
// Status flags: 16384 = display locked.
w.i(90, if v.locked { 16384 } else { 0 });
if !v.frozen_layers.is_empty() {
w.s(1001, dxf_ext::APP);
w.xdata(dxf_ext::frozen_xdata(&v.frozen_layers));
}
}
// Not yet written: images, wipeouts, tables, multileaders, unknown objects.
_ => {}
+33
View File
@@ -419,6 +419,39 @@ fn roundtrip(d: &Drawing) -> Drawing {
read_dxf(write_dxf(d).as_bytes()).unwrap()
}
#[test]
fn viewport_frozen_layers_roundtrip() {
let mut d = sample();
let paper = Space::Paper("Layout1".into());
let vp = |id: u32, frozen: Vec<String>| {
EntityKind::Viewport(Viewport {
center: Vec3::new(5.0, 4.0, 0.0),
width: 8.0,
height: 6.0,
view_center: Vec2::new(5.0, 2.5),
view_height: 12.0,
id,
locked: true,
frozen_layers: frozen,
layer_colors: Vec::new(),
})
};
d.add(&paper, Common::default(), vp(2, vec!["Walls".into(), "A B".into()])).unwrap();
d.add(&paper, Common::default(), vp(3, Vec::new())).unwrap();
let back = roundtrip(&d);
let frozen: Vec<(u32, Vec<String>)> = back
.layouts
.iter()
.flat_map(|l| l.entities.iter())
.filter_map(|e| match &e.kind {
EntityKind::Viewport(v) => Some((v.id, v.frozen_layers.clone())),
_ => None,
})
.collect();
assert!(frozen.contains(&(2, vec!["Walls".to_string(), "A B".to_string()])), "{frozen:?}");
assert!(frozen.contains(&(3, Vec::new())), "{frozen:?}");
}
fn full_dim_style() -> DimStyle {
DimStyle {
name: "Mech".into(),