Commit Graph
9 Commits
Author SHA1 Message Date
Hakan Seven 9b58ca8a93 Harden parametric sketch constraints 2026-09-11 09:45:57 +03:00
Felix RiestraandClaude Sonnet 5 eb96e8b6ed Fix silent TTF-fallback failures for variable system fonts (Turkish 'Ğ')
Root cause (found by instrumenting build_fallback and reading
ttf-parser's own source, not guessed): cosmic-text's fallback search
picks macOS's system font (San Francisco / SFNS.ttf) for any codepoint
no stroke font or explicitly-requested family covers. It's a variable
TrueType font, and ttf-parser's outline_glyph() resolves a variable
glyph's contours through its gvar table's deltas relative to whatever
variation coordinates are currently set on the Face — an unset Face
has none, so outline_glyph silently returns None (not an error) for
such a glyph. The caller then still returned Some(Glyph { strokes:
vec![], .. }): a "resolved" glyph with nothing to render, no error
anywhere.

Two-part fix:
1. pin_default_variations() sets every variation axis to its own
   default value before outlining, applied at all TTF outline-
   extraction sites (both build_fallback variants, both build_shaped
   variants, and the plain by-family glyph() lookup). This alone
   wasn't sufficient for San Francisco specifically — even pinned, its
   outline still didn't resolve for the glyphs this bug was found on,
   apparently because ttf-parser can't retrieve base glyf data gvar
   needs for at least some of that font's accented Latin glyphs.
2. So build_fallback() now treats "resolved a glyph ID but couldn't
   extract its outline" as a real failure (outline_from_face returns
   None, not an empty glyph) and falls through to a direct fontdb scan
   for any other installed font that also covers the character and
   can actually be outlined, rather than silently giving up.

Full workspace test suite: 813 passed, 0 failed (previously 812
passed, 1 failed — this was the one pre-existing failure carried
through the entire session).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 21:16:58 +02:00
Hakan Seven 53cf31f33d feat(web): unify fonts and refine viewcube
Preload one language-aware font resource across the interface, drawing text, and navigation labels.\n\nRender the navigation cube, ring, outlines, and labels through a 4x MSAA target.
2026-08-03 15:28:51 +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.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