Empty boxes instead of characters: it's a font problem, not an encoding problem
You see a row of empty rectangles, or a diamond with a question mark, where readable text should be. The instinct is to reach for encoding — but if the surrounding text renders correctly and only some characters are missing, the data is almost certainly fine and the font is the problem. A font can only draw the characters it was built to draw; anything outside that set gets substituted with a placeholder glyph, commonly called tofu because of its shape.
How to tell a font problem from an encoding problem apart quickly
The two failures look similar at a glance but have opposite signatures, and telling them apart takes one check: copy the broken text and paste it somewhere else, or inspect the underlying string value directly rather than the rendered screen.
- If the pasted or inspected text is the correct character (say, a kanji) but the screen shows a box — that is a font problem. The data is right; nothing can draw it.
- If the pasted or inspected text is itself wrong — unrelated characters, or U+FFFD REPLACEMENT CHARACTER — that is an encoding or mojibake problem. The data was corrupted before it ever reached rendering.
- A reliable tell: tofu boxes are usually uniform in size and shape (often a fixed rectangle or a dotted-outline box with a code point printed inside it), while mojibake produces varied, readable-looking-but-wrong characters.
Glyph coverage: why a font draws some characters and not others
A font file is, at its core, a lookup table from character to drawing instructions, plus the drawings themselves. No font covers the full range of characters that Unicode defines — building and shipping every glyph for every script would make the file enormous and mostly unused for any single project. Font authors choose a coverage set based on the languages they are targeting, and anything outside that set has no drawing to show.
This means a font can be entirely correct for the language it was designed for and still fail completely on a different one. A font built for Latin-script European languages typically has zero coverage for CJK ideographs; a font built for Japanese may still lack specific rare kanji, emoji, or symbols used in your UI.
Font fallback chains, and why they sometimes don't help
Most rendering systems do not stop at a single font. When the primary font lacks a glyph, they walk a fallback chain — a prioritized list of alternate fonts — and use the first one in that list that does have the glyph. This is what usually saves you from tofu in everyday software: the system silently substitutes a different, installed font for the characters your primary font can't draw.
This safety net breaks down in two common situations in games specifically. First, many game engines render text through a custom text system rather than the operating system's own text layer, and that custom system often uses exactly one font with no fallback chain configured at all — a missing glyph there has nowhere to fall back to. Second, even where a fallback chain exists, it can only fall back to fonts that are actually available on that device or bundled with the game; a fallback chain configured for a developer's desktop environment may have nothing to fall back to on a player's device.
// Example: a custom UI text renderer with one font and no fallback
const label = "コンティニュー"; // fine — this font covers Japanese kana
const label2 = "繼續"; // Traditional Chinese — this glyph is outside
// the font's coverage → renders as tofu, even
// though the string value itself is correctWhy CJK fonts are large, and what that means for your project
Chinese, Japanese, and Korean text uses thousands of distinct ideographs rather than a small alphabet, so a font that covers them adequately has to ship thousands of individually drawn glyphs. That makes CJK-capable fonts substantially larger than Latin-only fonts, and it is a real, deliberate cost trade-off for teams choosing which fonts to bundle — a project that adds Japanese or Chinese support has to budget font size, not just translation, and often can't simply reuse whatever font was already in the build.
What to check when only some characters are boxes
Partial tofu — most of the text renders fine, a handful of specific characters don't — is the most common real-world case and has a specific checklist.
- Confirm the underlying string is correct first (see the copy/inspect check above) — don't debug fonts for what is actually mojibake.
- Check whether the missing characters are rare kanji, symbols, or emoji rather than common characters; font coverage sets often include the common set and cut off the long tail.
- Check whether the missing characters come from a specific source — a name, a place name, a symbol used only in one string — since coverage gaps often cluster around exactly the kind of text that wasn't in the font author's target list.
- If a fallback chain is configured, confirm the fallback font is actually bundled with the build or installed on the test device, not just present on the machine that authored the UI.