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:
Hakan Seven 2026-04-06 14:37:23 +03:00
commit 1db3ad6a33
11 changed files with 429 additions and 28 deletions

View file

@ -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 {