Skip to content

Fix the live tofu in jax_intro, without trading it for subscript tofu#78

Merged
mmcky merged 2 commits into
mainfrom
fix/restore-cjk-font-config
Jul 24, 2026
Merged

Fix the live tofu in jax_intro, without trading it for subscript tofu#78
mmcky merged 2 commits into
mainfrom
fix/restore-cjk-font-config

Conversation

@mmcky

@mmcky mmcky commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Restores the font block in jax_intro.md, whose figure title PRNG 密钥拆分树 has been rendering as five blank boxes live on the published site for roughly three months — the block was stripped in 4120371 (2026-04-12), the title was translated to Chinese two days later, and this edition has published three times since.

The fallback is load-bearing here rather than precautionary. This lecture's figure labels the split tree with key₀, key₁, subkey₁, key₂, subkey₂, key₃, subkey₃ and a vertical ellipsis — eight glyphs that Source Han Serif SC does not contain. Registering it as the sole font.family entry would have fixed the 5-character title and broken those 8 labels, which render correctly today. That is a wash at best, and silent in both directions.

Note this edition uses _fonts/ where the other two use fonts/, and the block carries # i18n markers. Both are preserved here; standardising the two paths is a separate item in the program review.

Chinese figure labels in these lectures render as tofu — blank rectangles — because the notebook never registers a CJK font. matplotlib falls back to DejaVu Sans, which has no CJK coverage, emits a UserWarning, substitutes boxes, and writes a perfectly valid PNG. Nothing fails.

Two changes, and the second is the interesting one

1. Register the font where it was missing, following this edition's existing convention and path.

2. Give font.family a fallback. This is a deliberate deviation from the single-entry form used elsewhere in the estate, and it is a defect fix rather than a style choice.

Setting font.family to a single entry removes matplotlib's per-glyph fallback. Source Han Serif SC follows Adobe-GB1, which omits subscript digits (U+2080–U+2083), the vertical ellipsis (U+22EE) and the symbol Greek forms (U+03F5 ϵ, U+03D5 ϕ) — characters these lectures genuinely use in labels. So the naive fix would have swapped one set of blank boxes for another.

Measured on matplotlib 3.11.1 against this repo's own font file, rendering a label containing 密钥拆分树, key₀, , ϵ and ϕ:

font.family missing-glyph warnings
['Source Han Serif SC'] 4
['Source Han Serif SC', 'DejaVu Sans'] 0

CJK still comes from Source Han Serif; everything outside Adobe-GB1 now falls back instead of vanishing.

Why this was invisible

The missing-glyph warning is raised inside the Jupyter kernel subprocess. Sphinx's -W only escalates Sphinx-logger warnings, so CI never sees it — myst-nb renders it into the published page as stderr output instead. No CI log in the estate has ever contained findfont or Glyph … missing.

A detector now exists (bin/check-tofu in project-translation), validated against the live sites. It found pages that source-level analysis missed, because it reads what was actually rendered.

Background

Full history, the argument against reverting to text.usetex, and the recommendation to replace per-lecture injection with a build-level mechanism: project-translation reports/2026-07-24-cjk-font-rendering-review.md. Engine side: action-translation#182 (resync strips these blocks; the guardrail is prompt prose).

🤖 Generated with Claude Code

mmcky and others added 2 commits July 24, 2026 12:05
The PRNG key-splitting figure sets a Chinese axis title ("PRNG 密钥拆分树"),
but this lecture never registers a CJK font. matplotlib therefore falls
back to DejaVu Sans, which has no CJK coverage, and the title renders as
blank boxes ("tofu"). Nothing errors and a valid PNG is written, so the
defect is silent -- it only shows up in the published output.

Adds this edition's standard font block to the existing import cell,
immediately after the matplotlib import, so it runs before any figure is
drawn. The block is byte-for-byte identical to the one already carried by
debugging.md, numba.md and the other 15 lectures in this repo, and the
font path resolves to the tracked asset lectures/_fonts/SourceHanSerifSC-SemiBold.otf.

See #77

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nother

jax_intro's figure labels the split tree with key₀, key₁, subkey₁ ... and a
vertical ellipsis. Source Han Serif SC follows Adobe-GB1 and contains none of
U+2080-2083 or U+22EE, so registering it as the sole font.family entry would
have fixed the title (5 CJK characters) while breaking 8 label glyphs that
render correctly today — a wash at best, and silent either way.

Measured on matplotlib 3.11.1 against this repo's own font:

    font.family = ['Source Han Serif SC']                  -> 4 missing-glyph warnings
    font.family = ['Source Han Serif SC', 'DejaVu Sans']   -> 0

Deliberately deviates from the single-entry dialect used elsewhere here.
Copilot AI review requested due to automatic review settings July 24, 2026 02:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes CJK “tofu” (blank-box) rendering in lectures/jax_intro.md by restoring matplotlib font registration and configuring font.family with an explicit fallback so both Chinese titles and non-CJK glyphs (e.g., subscripts, vertical ellipsis, Greek symbol forms) render correctly in generated figures.

Changes:

  • Register the bundled Source Han Serif SC font via matplotlib.font_manager in the lecture’s import cell (_fonts/SourceHanSerifSC-SemiBold.otf).
  • Set mpl.rcParams['font.family'] to ['Source Han Serif SC', 'DejaVu Sans'] to allow fallback for glyphs not covered by Source Han Serif SC.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mmcky
mmcky merged commit 34be2ea into main Jul 24, 2026
3 checks passed
@mmcky
mmcky deleted the fix/restore-cjk-font-config branch July 24, 2026 04:43
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.

2 participants