From 4f01cca2fc67b36cb30a7a2600088b367075a2fb Mon Sep 17 00:00:00 2001 From: Bill Traynor Date: Tue, 1 Sep 2026 06:21:04 -0400 Subject: [PATCH] fix(theme): restore symbol coverage lost when M+ 1p was repointed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit d93e7bf repointed `M+ 1p Fallback` from fonts/mplus-1p-regular-fallback.ttf to GEM_FONTS_DIR/mplus1p-regular-fallback.ttf so that hard line breaks keep the body font's line height. The two copies are not nested — neither is a superset of the other: local copy 6726 codepoints, 1243 of them in no other font in the chain bundled copy 6982 codepoints, 1504 of them absent from the local copy The bundled copy adds U+000A, U+200B, U+202F, U+2060 and a wider CJK range. The local copy carries IPA extensions and a set of dingbats, among them U+2718 HEAVY BALLOT X. Repointing the entry silently dropped that 1243 and left the file in fonts/ shipped but unreferenced. 66df4a2 fixed the list markers by moving them onto glyphs JetBrainsMono maps directly, which is the right fix there because the marker has its own font family. Document body text has no such escape: its chain is body -> M+ 1p Fallback -> Noto Sans -> Noto Emoji, and a spec that writes U+2718 in a table now gets WARNING: Could not locate the character `✘' (✘) in the following fonts: body, M+ 1p Fallback, Noto Sans, Noto Emoji which is fatal for any build using --failure-level=WARN, as riscv-cheri does. U+2714 on the same line still resolves, because the bundled copy happens to map it — so the pair renders inconsistently even when the build is allowed to pass. Register the local copy under a second name and append it to the end of the fallback chain. Nothing is removed and nothing is reordered: the bundled copy still comes first and still decides line feed and CJK, and the added entry is reachable only for codepoints no earlier font provides. Verified in ghcr.io/riscv/riscv-docs-base-container-image with a document containing a U+2714/U+2718 table, a `+` hard-break block and three nested list levels, built with the same flags riscv-cheri uses: * before: 1 warning, exit 1; after: 0 warnings, exit 0 * U+2718 moves from a missing-glyph box to mplus-1p-regular; U+2714 is unchanged, still served by the bundled copy * hard-break baseline advances stay at 13.980/13.979pt, identical before and after and unchanged from 66df4a2 * list markers still render in JetBrainsMono-Regular; no new font is pulled into the marker chain * of 28 text spans, only the 3 U+2718 spans differ Co-Authored-By: Claude Opus 5 Signed-off-by: Bill Traynor --- themes/riscv-pdf.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/themes/riscv-pdf.yml b/themes/riscv-pdf.yml index 07f3e37..273646d 100644 --- a/themes/riscv-pdf.yml +++ b/themes/riscv-pdf.yml @@ -50,10 +50,22 @@ font: italic: GEM_FONTS_DIR/notosans-italic-subset.ttf bold_italic: GEM_FONTS_DIR/notosans-bold_italic-subset.ttf Noto Emoji: GEM_FONTS_DIR/notoemoji-subset.ttf + # The copy of M+ 1p in fonts/ and the copy bundled with Asciidoctor PDF have + # disjoint coverage: the bundled one maps U+000A and a wider CJK range, the + # local one maps ~1240 codepoints the bundled one lacks, including IPA + # extensions and dingbats such as U+2718. Keep the bundled copy first so it + # continues to decide line feed and CJK, and consult the local copy last, + # only for codepoints no other font in the chain provides. + M+ 1p Fallback Extra: + normal: mplus-1p-regular-fallback.ttf + bold: mplus-1p-regular-fallback.ttf + italic: mplus-1p-regular-fallback.ttf + bold_italic: mplus-1p-regular-fallback.ttf fallbacks: - M+ 1p Fallback - Noto Sans - Noto Emoji + - M+ 1p Fallback Extra svg: fallback-font-family: M+ 1mn page: