Skip to content

feat: WASM playground with LinearMetrics text fix and layout diagnostics#8

Merged
RoboNET merged 25 commits intomainfrom
feat/wasm-playground
Mar 10, 2026
Merged

feat: WASM playground with LinearMetrics text fix and layout diagnostics#8
RoboNET merged 25 commits intomainfrom
feat/wasm-playground

Conversation

@RoboNET
Copy link
Copy Markdown
Owner

@RoboNET RoboNET commented Mar 10, 2026

Summary

  • WASM playground for FlexRender with Monaco editor, VFS, project system
  • Fix text measurement in WASM: LinearMetrics = true on SKFont eliminates FreeType integer advance quantization
  • Add layout diagnostics (contentW, intrinsicW, shapedW, resolvedTypeface) to playground Layout tab
  • Embedded Inter-Regular font for WASM (no system fonts available)
  • Bounds overlay toggle for visual debugging

Test plan

  • All 2753 tests pass (net8.0 + net10.0)
  • 87 CLI tests pass
  • text_styled snapshot updated for LinearMetrics change (6.36% diff)
  • CI passes on PR
  • Playground renders NDC receipts correctly in WASM

🤖 Generated with Claude Code

RoboNET added 25 commits March 9, 2026 18:40
Replace minimal test page with full IDE layout: Monaco YAML/JSON editors,
preview panel with tabs (Preview/Layout/Errors), toolbar with examples
dropdown and export buttons, drag-and-drop for fonts/images/content,
and 300ms debounced re-rendering. Fix implicit HotReload package conflict
with Central Package Management.
…ont loading via ResourceLoaders, bitmap guard

- Add explicit NativeFileReference for SkiaSharp WASM (workaround for empty SkiaSharpStaticLibraryPath)
- Embed Inter-Regular.ttf as default font since WASM has no system fonts
- Add async font preloading via IResourceLoader chain (FontManager.PreloadFontFromResourcesAsync)
- Make TemplatePreprocessor.RegisterFonts async, falling back to resource loaders when File.Exists fails
- MemoryResourceLoader: also match by Path.GetFileName for absolute path lookups
- Guard bitmap dimensions to minimum 1px to prevent SKImage.FromBitmap returning null
- Disable static asset fingerprinting for simpler dev workflow
- Fix examples: use correct YAML keys (layout: not elements:, path: not src:, add fixed: both)
…nd async font loading

Enable font rendering in WASM playground by embedding Inter-Regular.ttf as default font,
adding async font preloading from resource loaders (MemoryResourceLoader), and fixing
SkiaSharp native library linking. Disable asset fingerprinting for simpler dev workflow.
…port, examples

- Per-project VFS: each example/user project has its own files, YAML, JSON
- Auto-save to IndexedDB with debounce, project switching with race guard
- YAML autocomplete: schema-driven property/value suggestions + VFS file paths
- ZIP export/import: bundle project as ZIP, import via button or drag & drop
- 6 built-in examples: Simple Text, Flex Layout, Data Binding, Image Scaling,
  Dynamic Receipt (with conditional rendering, QR, overlay image), NDC Receipt
- Example assets loaded from example-assets/ on first seed
- Security: XSS escaping in layout inspector, ZIP path traversal rejection
- Reliability: readEntries batching, IDB versionchange handler, URL revoke defer
- GitHub Pages CI workflow for automated deployment
…s platforms

FreeType in WASM quantizes glyph advances to integers, causing text width
miscalculation and overlapping elements. Setting LinearMetrics=true on SKFont
uses font design table metrics (fractional) instead of hinted metrics,
matching macOS CoreText behavior.

Also adds bounds overlay toggle and font diagnostics to playground UI.
Add contentW, intrinsicW, shapedW, resolvedTypeface diagnostic fields
to LayoutNode and playground layout JSON for text rendering debugging.
Update text_styled snapshot for LinearMetrics change.
…late

Add Inter-Regular.ttf to example-assets so it appears in VFS file tree.
All examples now explicitly declare the font in assets list.
Fix Data Binding example: add as:item to each loop for string arrays.
- Remove reflection (Assembly.GetExecutingAssembly) for AOT safety
- Gate diagnostics behind LayoutDiagnostics record + EnableDiagnostics flag
- Remove InternalsVisibleTo for Playground, make ResourceLoaders public
- Use ConcurrentDictionary in MemoryResourceLoader for thread safety
- Add 10MB resource size limit in MemoryResourceLoader
- Fix silent catch in FontManager.PreloadFontFromResourcesAsync
- Fix race condition with atomic AddOrUpdate in FontManager
- Add min 1px bitmap guard to all Render overloads
- Escape innerHTML in context menu for XSS safety
- Remove leftover debug variable in LayoutEngine
- Add playground link to README, wiki Home and Getting Started
…a from color picker

- FontManager: deferred disposal pattern for shared typefaces, WASM guards
  on system font APIs, resource loader fallback for font loading
- PlaygroundApi: remove all console logs, add GetLastError() for error
  observability, guard native property access with IsFileLoaded()
- Monaco editor: custom DocumentColorProvider that strips alpha channel
  from hex colors (FlexRender doesn't support alpha)
- AGENTS.md: document WASM playground testing with agent-browser
… family resolution

LoadTypefaceByFamily and LoadTypefaceVariant filtered by _fileLoadedTypefaces
before calling GetTypeface, but _fileLoadedTypefaces is only populated during
lazy loading via GetTypeface → LoadTypeface. Fonts registered via RegisterFont
(which only populates _fontPaths) were skipped, falling back to system fonts.

Fix: call GetTypeface first to trigger lazy file loading, then check
_fileLoadedTypefaces to determine if the font is safe to inspect.

Also adds 27 new FontManager unit/integration tests and Font-Loading.md wiki.
@RoboNET RoboNET merged commit acb2121 into main Mar 10, 2026
6 checks passed
@RoboNET RoboNET deleted the feat/wasm-playground branch March 10, 2026 13:34
RoboNET added a commit that referenced this pull request Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant