DWF/DGN underlays: clipping, layers, text, 3D DGN, colours and zoom extents

- PDFOSNAP, DWFOSNAP and DGNOSNAP are separate; UOSNAP sets them all and
  reads 2 while they differ. Enable Snap switches the selected kind's.
- DWFCLIP / DGNCLIP clip their own kind with the kind's prompts and message;
  CLIP routes DWF and DGN underlays there; Enter at a corner asks again.
- The right-edge underlay tools show for DWF and DGN too (import is PDF
  only).
- Underlay layers: DGN levels (V8 level table, "Default" listed as "0"; V7
  used levels named from the level name table), hidden through the layer
  override data with the DGN placeholder string first; a plotted DWF has
  none.
- V8 colour read from its colour word (by level, index, or a true colour
  drawn as its nearest index); 3D V8 elements drawn in plan (lines, line
  strings, ellipses and arcs by their orientation, text); a model's extent
  includes its text.
- DWF 6 TrueType text (font, height, rotation from the font opcode) and DWFx
  glyph runs are drawn; the default W2D colour map is the measured one.
- Contrast pulls lightness towards a per-kind pivot as measured (PDF 0.5,
  DWF 0.243, DGN 0.65).
- Zoom extents includes raster images and underlays whose frames are hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-09-28 16:10:01 +03:00
1 parent 1cbe89ef62
commit 56ecf786f1
41 files changed
+593 -147

No files matched your search

+34 -9
View File
@@ -600,15 +600,40 @@ pub fn circle_of(sp: &SubPath) -> Option<([f64; 2], f64)> {
// ── Snapping ────────────────────────────────────────────────────────────────
static PDF_OSNAP: AtomicBool = AtomicBool::new(true);
/// PDFOSNAP, DWFOSNAP and DGNOSNAP: whether object snaps find the geometry
/// inside underlays of each kind.
static UNDERLAY_OSNAP: [AtomicBool; 3] = [AtomicBool::new(true), AtomicBool::new(true), AtomicBool::new(true)];
/// PDFOSNAP: whether object snaps find the geometry inside PDF underlays.
pub fn pdf_osnap() -> bool {
PDF_OSNAP.load(Ordering::Relaxed)
fn osnap_slot(kind: codec::entities::UnderlayType) -> &'static AtomicBool {
match kind {
codec::entities::UnderlayType::Pdf => &UNDERLAY_OSNAP[0],
codec::entities::UnderlayType::Dwf => &UNDERLAY_OSNAP[1],
codec::entities::UnderlayType::Dgn => &UNDERLAY_OSNAP[2],
}
}
pub fn set_pdf_osnap(on: bool) {
PDF_OSNAP.store(on, Ordering::Relaxed);
pub fn underlay_osnap(kind: codec::entities::UnderlayType) -> bool {
osnap_slot(kind).load(Ordering::Relaxed)
}
pub fn set_underlay_osnap(kind: codec::entities::UnderlayType, on: bool) {
osnap_slot(kind).store(on, Ordering::Relaxed);
}
/// UOSNAP: 1 when snaps find every kind of underlay geometry, 0 when none,
/// 2 when the kinds differ.
pub fn uosnap() -> i16 {
match UNDERLAY_OSNAP.iter().filter(|s| s.load(Ordering::Relaxed)).count() {
0 => 0,
n if n == UNDERLAY_OSNAP.len() => 1,
_ => 2,
}
}
pub fn set_uosnap(on: bool) {
for slot in &UNDERLAY_OSNAP {
slot.store(on, Ordering::Relaxed);
}
}
/// Most snap points one underlay contributes.
@@ -623,7 +648,7 @@ pub fn underlay_snap_points(
document: &codec::CadDocument,
) -> Vec<(glam::DVec3, crate::scene::model::wire_model::SnapHint)> {
use crate::scene::model::wire_model::SnapHint;
if !pdf_osnap() || !u.flags.contains(codec::entities::UnderlayDisplayFlags::ON) {
if !underlay_osnap(u.underlay_type) || !u.flags.contains(codec::entities::UnderlayDisplayFlags::ON) {
return Vec::new();
}
let Some(def) = crate::entities::underlay::definition(u, document) else {
@@ -675,7 +700,7 @@ fn underlay_vectors(
codec::entities::UnderlayType::Pdf => {
page_vectors(&super::pdf_layers::underlay_source(u, &def.file_path), page)
}
kind => super::underlay_vector::page_vectors(kind, &def.file_path, page),
kind => super::underlay_vector::page_vectors(kind, &def.file_path, page, &super::pdf_layers::hidden_layers(u)),
}
}
@@ -698,7 +723,7 @@ pub fn underlay_snap_geometry(
u: &codec::entities::Underlay,
document: &codec::CadDocument,
) -> Vec<SnapPiece> {
if !pdf_osnap() || !u.flags.contains(codec::entities::UnderlayDisplayFlags::ON) {
if !underlay_osnap(u.underlay_type) || !u.flags.contains(codec::entities::UnderlayDisplayFlags::ON) {
return Vec::new();
}
let Some(def) = crate::entities::underlay::definition(u, document) else {