Feat: implement CTB/STB plot style table with PDF export integration
- src/io/plot_style.rs: PlotStyleTable and PlotStyleEntry data structures; CTB reader (deflate/zlib decompressed text format) with ACI→RGB and ACI→lineweight lookup; CTB writer (zlib compressed); LW_TABLE constant - src/io/pdf_export.rs: accept optional PlotStyleTable; apply ACI color and lineweight overrides during PDF rendering - src/scene/wire_model.rs: add `aci: u8` field to carry ACI index - src/scene/render.rs: render_style() now returns ACI alongside RGBA - src/scene/mod.rs + tessellate.rs: propagate aci through wire building - app: PlotStyleLoad/Loaded/Clear messages and handlers; PLOTSTYLE LOAD | CLEAR | STATUS command; active_plot_style state on H7CAD - flate2 added as dependency Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
911e36ba04
commit
1db3ad6a33
11 changed files with 429 additions and 28 deletions
|
|
@ -456,12 +456,12 @@ impl Scene {
|
|||
)];
|
||||
}
|
||||
|
||||
let (entity_color, pattern_length, pattern, line_weight_px) = self.render_style(e);
|
||||
let (entity_color, pattern_length, pattern, line_weight_px, aci) = self.render_style(e);
|
||||
let lt_scale = e.common().linetype_scale as f32;
|
||||
let lt_name = self.resolved_linetype_name(e);
|
||||
|
||||
if let EntityType::Dimension(dim) = e {
|
||||
return tessellate::tessellate_dimension(
|
||||
let mut wires = tessellate::tessellate_dimension(
|
||||
&self.document,
|
||||
h,
|
||||
dim,
|
||||
|
|
@ -469,6 +469,8 @@ impl Scene {
|
|||
entity_color,
|
||||
line_weight_px,
|
||||
);
|
||||
for w in &mut wires { w.aci = aci; }
|
||||
return wires;
|
||||
}
|
||||
|
||||
if let EntityType::Insert(ins) = e {
|
||||
|
|
@ -478,7 +480,7 @@ impl Scene {
|
|||
.cloned()
|
||||
.map(crate::modules::home::modify::explode::normalize_insert_entity)
|
||||
.flat_map(|sub| {
|
||||
let (sub_color, sub_pattern_length, sub_pattern, sub_line_weight_px) =
|
||||
let (sub_color, sub_pattern_length, sub_pattern, sub_line_weight_px, sub_aci) =
|
||||
self.render_style(&sub);
|
||||
let mut wire = tessellate::tessellate(
|
||||
&self.document,
|
||||
|
|
@ -491,12 +493,13 @@ impl Scene {
|
|||
sub_line_weight_px,
|
||||
);
|
||||
wire.name = h.value().to_string();
|
||||
wire.aci = sub_aci;
|
||||
vec![wire]
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
let base = tessellate::tessellate(
|
||||
let mut base = tessellate::tessellate(
|
||||
&self.document,
|
||||
h,
|
||||
e,
|
||||
|
|
@ -506,6 +509,7 @@ impl Scene {
|
|||
pattern,
|
||||
line_weight_px,
|
||||
);
|
||||
base.aci = aci;
|
||||
|
||||
if let Some(clt) = crate::linetypes::complex_lt(lt_name) {
|
||||
let wires = complex_lt::apply_along(
|
||||
|
|
@ -1966,6 +1970,7 @@ fn paper_boundary_wire(x0: f32, y0: f32, x1: f32, y1: f32) -> WireModel {
|
|||
line_weight_px: 1.5,
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,9 +150,10 @@ impl shader::Primitive for Primitive {
|
|||
// ── Render-style helpers (impl Scene) ────────────────────────────────────
|
||||
|
||||
impl Scene {
|
||||
pub(super) fn render_style(&self, e: &EntityType) -> ([f32; 4], f32, [f32; 8], f32) {
|
||||
/// Returns (entity_color, pattern_length, pattern, line_weight_px, aci).
|
||||
pub(super) fn render_style(&self, e: &EntityType) -> ([f32; 4], f32, [f32; 8], f32, u8) {
|
||||
let layer_name = &e.common().layer;
|
||||
let entity_color = {
|
||||
let (entity_color, aci) = {
|
||||
let ec = &e.common().color;
|
||||
let resolved = if *ec == AcadColor::ByLayer {
|
||||
self.document
|
||||
|
|
@ -163,9 +164,13 @@ impl Scene {
|
|||
} else {
|
||||
ec
|
||||
};
|
||||
let aci = match resolved {
|
||||
AcadColor::Index(i) => *i,
|
||||
_ => 0,
|
||||
};
|
||||
let [r, g, b, _] = tessellate::aci_to_rgba(resolved);
|
||||
let alpha = 1.0 - e.common().transparency.as_percent() as f32;
|
||||
[r, g, b, alpha]
|
||||
([r, g, b, alpha], aci)
|
||||
};
|
||||
|
||||
let lt_name = self.resolved_linetype_name(e);
|
||||
|
|
@ -191,7 +196,7 @@ impl Scene {
|
|||
.unwrap_or(1.0)
|
||||
};
|
||||
|
||||
(entity_color, pattern_length, pattern, line_weight_px)
|
||||
(entity_color, pattern_length, pattern, line_weight_px, aci)
|
||||
}
|
||||
|
||||
pub(super) fn resolved_linetype_name<'a>(&'a self, e: &'a EntityType) -> &'a str {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ pub fn tessellate(
|
|||
line_weight_px,
|
||||
snap_pts: te.snap_pts,
|
||||
tangent_geoms: te.tangent_geoms,
|
||||
key_vertices: te.key_vertices,
|
||||
aci: 0,
|
||||
key_vertices: te.key_vertices,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +120,8 @@ pub fn tessellate(
|
|||
line_weight_px: 1.0,
|
||||
snap_pts: te.snap_pts,
|
||||
tangent_geoms: te.tangent_geoms,
|
||||
key_vertices: te.key_vertices,
|
||||
aci: 0,
|
||||
key_vertices: te.key_vertices,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -138,7 +140,8 @@ pub fn tessellate(
|
|||
line_weight_px,
|
||||
snap_pts: te.snap_pts,
|
||||
tangent_geoms: te.tangent_geoms,
|
||||
key_vertices: te.key_vertices,
|
||||
aci: 0,
|
||||
key_vertices: te.key_vertices,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -155,7 +158,8 @@ pub fn tessellate(
|
|||
line_weight_px,
|
||||
snap_pts: te.snap_pts,
|
||||
tangent_geoms: te.tangent_geoms,
|
||||
key_vertices: te.key_vertices,
|
||||
aci: 0,
|
||||
key_vertices: te.key_vertices,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -171,7 +175,8 @@ pub fn tessellate(
|
|||
line_weight_px,
|
||||
snap_pts: te.snap_pts,
|
||||
tangent_geoms: te.tangent_geoms,
|
||||
key_vertices: te.key_vertices,
|
||||
aci: 0,
|
||||
key_vertices: te.key_vertices,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +194,7 @@ pub fn tessellate(
|
|||
points,
|
||||
color,
|
||||
selected,
|
||||
aci: 0,
|
||||
pattern_length,
|
||||
pattern,
|
||||
line_weight_px,
|
||||
|
|
@ -224,6 +230,7 @@ pub fn tessellate_dimension(
|
|||
points,
|
||||
color,
|
||||
selected,
|
||||
aci: 0,
|
||||
pattern_length: 0.0,
|
||||
pattern: [0.0; 8],
|
||||
line_weight_px,
|
||||
|
|
@ -274,6 +281,7 @@ fn tessellate_leader(
|
|||
line_weight_px,
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
}];
|
||||
}
|
||||
|
|
@ -335,6 +343,7 @@ fn tessellate_leader(
|
|||
points,
|
||||
color,
|
||||
selected,
|
||||
aci: 0,
|
||||
pattern_length: 0.0,
|
||||
pattern: [0.0; 8],
|
||||
line_weight_px,
|
||||
|
|
@ -445,7 +454,8 @@ fn tessellate_multileader(
|
|||
line_weight_px,
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
key_vertices: key_verts,
|
||||
aci: 0,
|
||||
key_vertices: key_verts,
|
||||
}];
|
||||
|
||||
// Render text content as MText wire
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ pub struct WireModel {
|
|||
pub pattern: [f32; 8],
|
||||
/// Rendered line width in screen pixels (half-width = line_weight_px / 2).
|
||||
pub line_weight_px: f32,
|
||||
/// ACI color index (1-255). 0 means true-color or unknown (no CTB lookup).
|
||||
pub aci: u8,
|
||||
/// Pre-baked snap candidates (Center, Node, Quadrant, Insertion).
|
||||
pub snap_pts: Vec<(glam::Vec3, SnapHint)>,
|
||||
/// Per-segment tangent geometry for Tangent snap.
|
||||
|
|
@ -67,6 +69,7 @@ impl WireModel {
|
|||
points,
|
||||
color,
|
||||
selected,
|
||||
aci: 0,
|
||||
pattern_length: 0.0,
|
||||
pattern: [0.0; 8],
|
||||
line_weight_px: 1.0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue