Skip to content

Registered icon-font TTFs render blank glyphs until table checksums/table directory are recomputed — silent failure in the DWrite font path #16308

Description

@FaithfulAudio

Problem Description

Several stock icon-font TTFs render blank glyphs through RNW's new-arch text stack, even though they register into DirectWrite successfully and enumerate with correct family/cmap/name records. Re-emitting the same fonts with byte-identical glyph data through a minimal OpenType writer that only recomputes table checksums (incl. head.checkSumAdjustment) and rebuilds the table directory makes the very same fonts render. No outlines, metrics, or name records changed in the control case — only checksums/table-directory layout.

Fonts affected in our app (all stock files shipped in react-native-vector-icons 10.3.0): Ionicons, FontAwesome, Feather, Octicons, EvilIcons, AntDesign. These same files render fine in other Windows apps and on iOS/Android — icon-font-generator output frequently carries technically-stale checksums that everything else tolerates.

Root cause — diagnosed from behavior, NOT traced to a specific line (confidence stated honestly). Some layer of the RNW/DWrite font path applies stricter TTF validation than the rest of Windows: the fonts register and enumerate, but glyph rendering silently produces blanks until the checksums/table directory are made strictly valid. We have not identified whether the rejection happens in an RNW-side loader/validation step or in how DirectWrite validates faces the way RNW loads/uses them. The failure is completely silent — no warning, no error, just blank glyphs — which made this extremely expensive to diagnose.

Suggested fix direction: either align validation tolerance with what DirectWrite/Windows accepts elsewhere (these fonts work everywhere else), or keep the strictness but surface a diagnostic when a face fails validation, and document the requirement.

Related but distinct from #16306 (spaced family names fail to resolve — a lookup problem). This issue is about faces that resolve/enumerate but whose glyphs never render — a loader/validation problem. We hit both in the same integration; fixing one does not fix the other.

Steps To Reproduce

  1. Take stock Ionicons.ttf from react-native-vector-icons 10.3.0 (unmodified).
  2. Register it so DirectWrite sees it (we use the windows.sharedFonts package-manifest extension) and confirm via DirectWrite/WPF enumeration that the family is present with correct records.
  3. Render <Text style={{ fontFamily: 'Ionicons' }}>{glyph}</Text> with a mapped codepoint.
  4. Observe: blank output (not tofu boxes — blank), no diagnostics.
  5. Control: re-emit the same TTF recomputing all table checksums and rebuilding the table directory (glyph data untouched); replace the registered file.
  6. Glyphs now render.

Expected Results

Fonts that install and render everywhere else on Windows (and on iOS/Android) render in RNW — or, at minimum, a visible diagnostic is emitted when the font path refuses a face.

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 supply the affected TTFs, but the rendering path is core <Text> + DirectWrite; any TTF with stale table checksums should reproduce.

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

The decisive experiment is steps 3–6 above: identical glyph data, only checksums/table directory recomputed, blank → rendering.

Our production workaround: a dependency-free build-time Node script re-emits the Windows copies of all bundled icon fonts with recomputed checksums and a rebuilt table directory (the same pass that renames spaced families for #16306), registered via windows.sharedFonts.

Related: #16306 (spaced family-name resolution), #15750 (IProvideFontInfo font-loading unification), #15316 (custom .ttf support on new arch).

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 provide before/after font binaries or a minimal repro repo, and to test candidate fixes in our app.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: Triage 🔍New issue that needs to be reviewed by the issue management team (label applied by bot)

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions