Problem Description
On the new architecture, a fontFamily whose name contains a space (e.g. 'Material Icons') fails to resolve even though the font is registered and enumerable in DirectWrite — glyphs render as tofu / fall back to Segoe UI. The identical TTF re-emitted with a space-less family name ('MaterialIcons', name table IDs 1/16 rewritten, glyph outlines untouched) resolves and renders. The space in the requested family name is the only variable.
What we verified empirically (production app):
- Fonts registered via the packaged
windows.sharedFonts manifest extension land in DirectWrite's per-user system font collection; WPF/DirectWrite enumeration shows the family present under its spaced name (Material Icons), correct cmap/name records.
fontFamily: 'Material Icons' → tofu.
- Same file, family renamed to
MaterialIcons (only the OpenType name table changed) → renders correctly.
Root cause — diagnosed, NOT traced to a specific line (filing for visibility; confidence level stated honestly). The resolution lives in the DirectWrite text-layout path — vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager and/or the font-collection/loader it uses — i.e. how the requested family string reaches CreateTextFormat / FindFamilyName. Plain DirectWrite handles spaced family names fine (Segoe UI is the platform default), so we suspect RNW-side handling of the fontFamily string (tokenizing/trimming, or the custom collection lookup) rather than DirectWrite itself. We could not pin the failing lookup with confidence from a shallow source read, so we did not attempt a patch.
Steps To Reproduce
- Take a TTF whose family name contains a space — e.g. stock
MaterialIcons.ttf from react-native-vector-icons (family name Material Icons).
- Register it so DirectWrite can see it (we use the
windows.sharedFonts package-manifest extension; confirm via any DirectWrite/WPF font enumeration that the family is present).
- Render
<Text style={{ fontFamily: 'Material Icons' }}>{''}</Text> (any mapped codepoint).
- Observe tofu / Segoe UI fallback.
- Control: rewrite the font's
name table so the family is MaterialIcons (no other change), request fontFamily: 'MaterialIcons' → glyphs render.
Expected Results
Spaced family names resolve exactly as space-less ones do (and as they do on iOS/Android, and in DirectWrite generally).
CLI version
18.0.0
Environment
System:
OS: Windows 11 10.0.26200 (ARM64 device; app builds and runs ARM64)
CPU: (6) x64 Apple Silicon (Windows-on-ARM)
Memory: 6.49 GB / 15.99 GB
Binaries:
Node: 22.15.0
Yarn: 4.5.1
npm: 10.9.2
SDKs:
Windows SDK versions: 10.0.19041.0, 10.0.22621.0, 10.0.26100.0
IDEs:
Visual Studio: 18.6.11822.322 (Community 2026), 17.14.37314.3 (Community 2022)
npmPackages (yarn 4 workspaces — `cli info` reports Not Found in-workspace):
react-native: 0.83.2
react-native-windows: 0.83.2 (New Architecture / Fabric composition)
Microsoft.WindowsAppSDK: 1.8
Community Modules
react-native-vector-icons 10.3.0 / @expo/vector-icons 15.1.1 are where the spaced-name fonts come from, but the bug is core: it reproduces with any registered TTF whose family name contains a space, rendered through core <Text>.
Target React Native Architecture
New Architecture (WinAppSDK) Only
Target Platform Version
10.0.22621
Visual Studio Version
Visual Studio 2026
Build Configuration
Debug
Snack, code example, screenshot, or link to a repository
Minimal probe is the two-step control above (steps 3 vs 5) — same file, same glyphs, only the family name differs.
Our production workaround: a dependency-free Node script re-emits the Windows copies of all affected fonts with space-less family names (rewriting name IDs 1/16 and recomputing table checksums), registered via windows.sharedFonts; a platform shim makes JS request the space-less names on Windows only.
Related issues: #15316 (umbrella: custom .ttf fontFamily support on new arch), #3463 (old-arch custom-font parity), #15750 (IProvideFontInfo font-loading unification). Related but distinct, filed separately: #16308 — registered stock icon TTFs render blank glyphs until table checksums/table directory are recomputed (loader validation vs. this issue's family-name lookup).
Context: found during a Windows hardening pass of a production RNW app (Facilitron FIT — RNW 0.83.2 new-arch, Windows 11 ARM64, WinAppSDK 1.8, 250% display scale). Sibling PRs from the same investigation: #16302, #16303, #16304. Happy to build a minimal repro repo or test candidate fixes in our app if useful.
Problem Description
On the new architecture, a
fontFamilywhose name contains a space (e.g.'Material Icons') fails to resolve even though the font is registered and enumerable in DirectWrite — glyphs render as tofu / fall back to Segoe UI. The identical TTF re-emitted with a space-less family name ('MaterialIcons', name table IDs 1/16 rewritten, glyph outlines untouched) resolves and renders. The space in the requested family name is the only variable.What we verified empirically (production app):
windows.sharedFontsmanifest extension land in DirectWrite's per-user system font collection; WPF/DirectWrite enumeration shows the family present under its spaced name (Material Icons), correctcmap/namerecords.fontFamily: 'Material Icons'→ tofu.MaterialIcons(only the OpenTypenametable changed) → renders correctly.Root cause — diagnosed, NOT traced to a specific line (filing for visibility; confidence level stated honestly). The resolution lives in the DirectWrite text-layout path —
vnext/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManagerand/or the font-collection/loader it uses — i.e. how the requested family string reachesCreateTextFormat/FindFamilyName. Plain DirectWrite handles spaced family names fine (Segoe UIis the platform default), so we suspect RNW-side handling of thefontFamilystring (tokenizing/trimming, or the custom collection lookup) rather than DirectWrite itself. We could not pin the failing lookup with confidence from a shallow source read, so we did not attempt a patch.Steps To Reproduce
MaterialIcons.ttffromreact-native-vector-icons(family nameMaterial Icons).windows.sharedFontspackage-manifest extension; confirm via any DirectWrite/WPF font enumeration that the family is present).<Text style={{ fontFamily: 'Material Icons' }}>{''}</Text>(any mapped codepoint).nametable so the family isMaterialIcons(no other change), requestfontFamily: 'MaterialIcons'→ glyphs render.Expected Results
Spaced family names resolve exactly as space-less ones do (and as they do on iOS/Android, and in DirectWrite generally).
CLI version
18.0.0
Environment
Community Modules
react-native-vector-icons10.3.0 /@expo/vector-icons15.1.1 are where the spaced-name fonts come from, but the bug is core: it reproduces with any registered TTF whose family name contains a space, rendered through core<Text>.Target React Native Architecture
New Architecture (WinAppSDK) Only
Target Platform Version
10.0.22621
Visual Studio Version
Visual Studio 2026
Build Configuration
Debug
Snack, code example, screenshot, or link to a repository
Minimal probe is the two-step control above (steps 3 vs 5) — same file, same glyphs, only the family name differs.
Our production workaround: a dependency-free Node script re-emits the Windows copies of all affected fonts with space-less family names (rewriting name IDs 1/16 and recomputing table checksums), registered via
windows.sharedFonts; a platform shim makes JS request the space-less names on Windows only.Related issues: #15316 (umbrella: custom .ttf
fontFamilysupport on new arch), #3463 (old-arch custom-font parity), #15750 (IProvideFontInfo font-loading unification). Related but distinct, filed separately: #16308 — registered stock icon TTFs render blank glyphs until table checksums/table directory are recomputed (loader validation vs. this issue's family-name lookup).Context: found during a Windows hardening pass of a production RNW app (Facilitron FIT — RNW 0.83.2 new-arch, Windows 11 ARM64, WinAppSDK 1.8, 250% display scale). Sibling PRs from the same investigation: #16302, #16303, #16304. Happy to build a minimal repro repo or test candidate fixes in our app if useful.