Skip to content

fix: render CJK glyphs in terminal (fontFamily + optional WebGL renderer)#823

Open
mhit wants to merge 1 commit into
siteboon:mainfrom
mhit:fix/terminal-cjk-rendering
Open

fix: render CJK glyphs in terminal (fontFamily + optional WebGL renderer)#823
mhit wants to merge 1 commit into
siteboon:mainfrom
mhit:fix/terminal-cjk-rendering

Conversation

@mhit
Copy link
Copy Markdown

@mhit mhit commented Jun 4, 2026

Summary

CJK characters (Japanese / Chinese / Korean) are frequently rendered as solid black boxes ("tofu") in the built-in xterm.js terminal, while the same text renders fine elsewhere in the app. This fixes the two compounding root causes.

Root cause

  1. fontFamily has no CJK font (src/components/shell/constants/constants.ts). Menlo, Monaco, "Courier New", monospace has no CJK coverage, so CJK can only come from the generic monospace fallback.
  2. WebGL renderer is loaded unconditionally (src/components/shell/hooks/useShellTerminal.ts). The xterm.js WebGL/Canvas renderer rasterizes glyphs into a texture atlas and handles fallback glyphs poorly, so CJK obtained via generic monospace frequently comes out as the missing-glyph box. The intermittent, per-glyph nature of the breakage is the signature of this atlas/fallback issue (a real OS coverage gap would drop all CJK).

Changes

  • Add cross-platform CJK monospace fallbacks to TERMINAL_OPTIONS.fontFamily, giving the glyph atlas an explicit CJK font to rasterize from.
  • Add isWebglDisabled() and gate the WebglAddon behind it, so the WebGL renderer can be turned off (falling back to the DOM renderer, which renders CJK reliably). Resolution order:
    1. localStorage['terminal-disable-webgl'] === 'true' (runtime, no rebuild)
    2. VITE_TERMINAL_DISABLE_WEBGL === 'true' (build-time default)
    • Defaults to keeping WebGL enabled, so behavior is unchanged unless opted out.

How to test

  1. Open the terminal and run echo 日本語テスト 中文 한국어.
  2. With the font change alone, CJK should render correctly in most environments.
  3. If boxes still appear, run localStorage.setItem('terminal-disable-webgl','true') in DevTools and reopen the terminal — the DOM renderer renders CJK reliably even with an imperfect font stack.

Notes / trade-offs

  • The DOM renderer is slower than WebGL for heavy output; that's why WebGL stays on by default and the opt-out is user-controllable. This relates to the font-configurability request in Feature/font customization #730.
  • No server-side changes; client rebuild only.

Fixes #822

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Enhanced terminal font rendering with better support for CJK characters (Japanese, Chinese, Korean)
    • Added option to disable WebGL renderer for improved compatibility on certain systems
    • Improved terminal initialization with graceful fallback handling

CJK characters (Japanese/Chinese/Korean) frequently rendered as black
boxes ("tofu") in the xterm.js terminal. Two compounding causes:

1. TERMINAL_OPTIONS.fontFamily had no CJK font, so CJK could only come
   from the generic `monospace` fallback, which the WebGL/Canvas glyph
   atlas rasterizes poorly (missing-glyph boxes).
2. The WebGL renderer was loaded unconditionally and handles fallback
   glyphs worse than the DOM renderer.

Changes:
- Add cross-platform CJK monospace fallbacks to fontFamily so the atlas
  has an explicit CJK font to rasterize from.
- Add isWebglDisabled() so the WebGL addon can be skipped (DOM renderer)
  via localStorage 'terminal-disable-webgl' or VITE_TERMINAL_DISABLE_WEBGL,
  which renders CJK reliably even with an imperfect font stack.

Fixes siteboon#822

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a0a169ed-e4b6-45d0-bbf5-62361ff554f5

📥 Commits

Reviewing files that changed from the base of the PR and between d9e9df1 and b18d04d.

📒 Files selected for processing (2)
  • src/components/shell/constants/constants.ts
  • src/components/shell/hooks/useShellTerminal.ts

📝 Walkthrough

Walkthrough

This PR fixes CJK character rendering in the built-in terminal by expanding the font family to include cross-platform CJK monospace fonts and introducing a WebGL renderer toggle. Users can disable the WebGL renderer via localStorage or environment variable to improve CJK glyph atlas rendering reliability.

Changes

Terminal CJK rendering and WebGL configuration

Layer / File(s) Summary
Terminal font stack and WebGL disablement configuration
src/components/shell/constants/constants.ts
TERMINAL_OPTIONS.fontFamily is updated to include CJK monospace fallbacks (Noto Sans Mono CJK, Meiryo, MS Gothic, Microsoft YaHei, PingFang SC, Hiragino Sans). New isWebglDisabled() function reads the terminal-disable-webgl localStorage key with fallback to VITE_TERMINAL_DISABLE_WEBGL environment variable, defended against access errors.
WebGL addon conditional loading in terminal hook
src/components/shell/hooks/useShellTerminal.ts
Terminal hook imports and uses isWebglDisabled() to conditionally load WebglAddon only when WebGL is enabled, preserving existing try/catch fallback for WebGL unavailability.

🐰 Boxes no more, the CJK glyphs now shine,
With fonts that know kanji, hanzi, and Korean line,
WebGL can step aside, let the DOM renderer reign,
And Japanese text flows—no more black-box pain!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately summarizes the main changes: adding CJK fonts and optional WebGL disabling to fix CJK glyph rendering in the terminal.
Linked Issues check ✅ Passed All code changes align with issue #822 requirements: expanded fontFamily with CJK fonts and implemented optional WebGL disabling via isWebglDisabled() helper.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing CJK rendering in the terminal; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

Terminal renders CJK (Japanese/Chinese/Korean) text as black boxes — WebGL renderer + Latin-only fontFamily

1 participant