Commit Graph
60 Commits
Author SHA1 Message Date
Hakan SevenandClaude Opus 4.8 a93271c1bd fix(block-cache): address PR211 review follow-ups
- expand_defn: dedup the <1px baseline LOD branch the same way the <5px
  greek branch does, so colour-split MTEXT no longer stacks N overlapping
  baselines (one per \C segment) over the same OBB.
- sysfont: memoise canonical_family_name process-wide. resolve_font calls
  it once per word on the MTEXT measure hot path and Face::resolve re-runs
  it right after; the fontdb query + linear family scans were uncached.
- dimension/multileader/table: reword the 6 fill_tris_low FIXMEs. They
  cited a stale line and the wrong consumer — these fills render on the
  top-level path (panic-safe .get().unwrap_or), not the block cache, so
  they cannot trip emit_wire's debug_assert. State the real status:
  latent f32-precision debt, not a crash. Also fix the mis-indented
  text-fill WireModel in dimension.rs.
- tests: add a host-independent colour-split test (two \C segments in a
  block keep ≥2 distinct wire colours — guards the per-wire colour fix)
  and a TTF-gated UTM fill test (paired, non-zero fill_tris_low). Note the
  arial-style test's LFF-fallback limitation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:57:51 +03:00
Hakan SevenandClaude Opus 4.8 415dbe08d4 refactor: move resource/IO root modules under io/
Relocate three root-level modules into io/, where they belong by concern:

- update_check.rs -> io/update_check.rs (its own doc-comment notes it
  mirrors how crate::io wraps blocking calls in async).
- patterns.rs, linetypes.rs -> io/ (standard resource catalogs parsed
  from asset files and populated into the document — IO-shaped work).

Fix the moved files' include_str! paths (one level deeper), add the
mod declarations to io/mod.rs, drop them from lib.rs/main.rs, and
re-point all crate:: references to crate::io::. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 23:06:40 +03:00
Hakan SevenandClaude Opus 4.8 dee5a05652 fix(text): address PR #180 review
Follow-up cleanups on the merged TTF-fill work:

- Drop the unconditional resolve_text_style log line — it fired for every
  text style and spammed ~7k stderr lines opening a single real drawing.
- Drop the per-glyph tessellation-error eprintln; a malformed font would
  otherwise log once per character. The glyph still falls back silently.
- Tessellate glyph fills with the nonzero winding rule (lyon defaults to
  even-odd, which mis-fills TrueType outlines whose contours overlap).
- Make the sysfont prefix fallback deterministic (sorted) and require ≥3
  chars so a 1–2 letter request can't grab an arbitrary family.
- Remove the unrelated windows-gnu --exclude-all-symbols linker flag that
  slipped into .cargo/config.toml.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 00:27:40 +03:00
Karim Jerbi 627761b629 fix(text): render TTF glyphs as solid fills, fix font fallback, correct Z-order
Text elements previously rendered as hollow wireframe outlines and sometimes
fell back to the wrong system font due to case-sensitive exact matching. Also,
the viewport background grid drew on top of solid entities.

Case-insensitive and partial-name fallback matching (e.g., mapping "arialn"
to "Arial Narrow") is now added to `sysfont::canonical_family_name`, ensuring
text resolves to the correct installed system font.

TrueType font contours are now triangulated into solid fills (`fill_tris`)
using `lyon_tessellation` in `ttf_glyph.rs`. To prevent the GPU from misclassifying
this 2D text as a 3D mesh (which broke flat shading), text tessellation splits
the output into separate outline and fill `WireModel`s.

The background grid is extracted from `SelectionCanvas` into `GridCanvas` and
moved beneath the 3D viewport to ensure proper layering. Finally, `DepthBiasState`
is enabled on all face/fill pipelines to apply a polygon offset, perfectly
resolving Z-fighting between coplanar wireframe lines and solid faces.
2026-06-25 18:17:01 +01:00
Hakan SevenandClaude Opus 4.7 c0f3d0de5e feat(render): double-single fills for the face3d pipeline
Table / PolyfaceMesh / greek-text / mleader-background fills go through
the face3d pipeline; their vertices were single f32 and quantized at UTM
scale. WireModel now carries a fill_tris_low residual (filled by the
tessellate Lines path), Face3DVertex gains position_low (location 3), and
face3d.wgsl reconstructs the eye-relative position from the pair. 3DFACE
quads built from key_vertices use a zero residual (no low source).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 18:28:52 +03:00
Hakan SevenandClaude Opus 4.7 97d6993768 refactor(wire): add WireModel.points_low parallel buffer (empty default)
Foundation for double-single positions: WireModel now carries an
index-paired f32 residual buffer (`points_low`) next to the existing
`points` high half. Empty means "all-zero residual", so every existing
constructor (interactive draw, previews) is unchanged in behaviour;
tessellation from CAD f64 will fill it in the next steps so vertex
precision survives at UTM-scale coordinates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 18:28:52 +03:00
Hakan SevenandClaude Opus 4.8 10e4c18ba7 chore: silence native and wasm build warnings
Gate target-specific code so neither build warns about the other's items:
native-only helpers (view, window icon, file dialogs, file association, plugin
host/guard/registry, self-update) are cfg'd to non-wasm; the wasm-only font
fallback (script_of / cjk_lang / request) is cfg'd to wasm. Drop an unused mut,
allow the few genuinely-conditional dead items (mesh_click_hit, GPU layout
helpers, parity stubs), and gate the embedded PlotSettings-unrelated dead
constants. Both targets now build clean (only the unavoidable nom/quick-xml
future-incompat dependency notice remains).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 02:03:34 +03:00
Hakan SevenandClaude Opus 4.8 54106ca9b0 feat(web): lazy per-script font loading for international CAD text
The web build has no system-font access, so CAD text in non-Latin scripts
(Cyrillic, Greek, CJK, …) rendered as nothing — build_fallback was a hard
None on wasm (#141). Instead, ship per-script Noto subsets under web/fonts
(one alphabet per file, SIL OFL 1.1) and fetch them lazily over HTTP the
first time a drawing uses that script, then outline glyphs with ttf-parser.

- web_font: Script enum + script_of (char → script font), a per-script
  store with lazy fetch, and a pending queue drained by the app loop.
- CJK is split by language (chinese/japanese/korean). Han ideographs share
  code points but differ by language, so the shared block is routed by the
  document's $DWGCODEPAGE (932→JP, 949→KR, GB/936→CN); kana is always
  Japanese, Hangul always Korean. Re-tessellates when the language changes.
- build_fallback (wasm) outlines from the fetched subset; clear_fallback_cache
  lets glyphs that missed while a font was in flight reappear on load.
- PollWebFonts subscription (web only) + WebFontLoaded message drive fetches.
- Trunk copy-dir serves web/fonts; nothing is bundled into the native binary
  (desktop keeps using system fonts).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 16:13:26 +03:00
Hakan SevenandClaude Opus 4.8 6996343e84 feat(wasm): open files in the browser
Wire up file open for the web build:

- `io::pick_and_load_web`: browser file picker → read bytes → parse via
  `load_bytes` → build caches, returning the same payload as the native
  loader so it feeds the shared `Message::FileOpened` handler.
- `Message::OpenFile` cfg-dispatches: native picks a path then loads on a
  worker thread; web picks + parses in one async step. The web branch also
  sets `opening` (the handler drops results when no open is in progress).
- Disable the cosmic-text shaping / fallback paths on wasm: the web has no
  system fonts, so cosmic-text panics with "no default font found". LFF
  stroke fonts (embedded) still render; LFF-missing glyphs are skipped.

Native build + 75 tests unchanged. Hatches still don't draw on the web.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 18:08:57 +03:00
Hakan SevenandClaude Opus 4.8 7fe7e0230d refactor(scene): group modules into role-based subfolders
Move the 30 flat modules under src/scene/ into six folders by role:
convert (entity→geometry), text (fonts/shaping), model (render models),
pick (hit-test/selection/grips/xclip), view (camera/transform/render),
cache (block + property caches). pipeline/ is unchanged.

Full path migration — all `scene::X` references become
`scene::<group>::X`, no compatibility re-exports. render.rs items that
were `pub(super)` (parent was scene) become `pub(in crate::scene)` to
keep their original scene-wide visibility.

No behavior change; build and tests are green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:33:46 +03:00