Skip to content

feat(libSceFont): open the other script files of a system font set - #8058

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
HQasper:claude/project-thread-md0z38
Oct 20, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
HQasper:claude/project-thread-md0z38

Conversation

@HQasper

@HQasper HQasper commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

What

sceFontOpenFontSet opened only a set's primary file, so a set that covers several scripts (..._JP_AR, ..._JPCJK_TH, ..._GBCJK, ...) reported its other scripts' characters as unsupported glyphs. A set now also opens the files of the scripts its type names (Vietnamese, Thai, Japanese, simplified Chinese, Hangul, Arabic), or their Noto substitutes, and a character the primary file lacks is measured, rendered, outlined and kerned with the first of them that has it. The script bits and the file order follow the SDK set names as shadPS4 lists them, not a console measurement; this is recorded in docs/dev/debt/libSceFont.md. docs/user/USAGE.md lists the extra files and the Noto Sans Arabic and Korean substitutes.

Tested

Linux (gcc, Release): guest_system_font, guest_font, guest_font_writing_line and the three font_face_lifetime tests pass. The new checks in guest_system_font open sets with Japanese, Chinese-first CJK, Hangul, Arabic and Vietnamese files and check metrics, an instance, kerning across files and rendered pixels; on unchanged main the test aborts at the first of them (line 132). No title was run.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 docs/user/USAGE.md
PR 5925 docs/user/USAGE.md
PR 6044 core/libs/tests/GuestSystemFont.cpp
PR 6171 docs/user/USAGE.md
PR 6586 docs/user/USAGE.md
PR 6788 docs/user/USAGE.md
PR 6946 docs/user/USAGE.md
PR 6947 docs/user/USAGE.md
PR 7642 docs/user/USAGE.md
PR 7800 docs/user/USAGE.md

@rahul05ranjan rahul05ranjan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This fills in a real gap in a careful way. Things I traced in the diff and confirmed:

  • FallbackFamilies bit logic matches the tests exactly: 0x1807A444 (scripts 0xA4) gets Japanese before ChineseGb while 0x1807AC44 (scripts 0xAC, hitting the 0x88 case) puts ChineseGb first, and the add lambda's dedupe means the later bare-0x80 add is a no-op rather than a duplicate. The Korean-face substitution index (substituteSubFont: 1 for Hangul) picking Noto Sans CJK's Korean face is the detail that makes the substitute path actually work.
  • The candidate dedupe via opened() is load-bearing: a Latin-primary set that fell back to NotoSans-Regular.ttf would otherwise re-open the same file as its Vietnamese fallback.
  • sceFontOpenFontInstance re-creating each fallback face per instance is the right ownership call — it keeps every handle with its own mutable FT_Face, so the FT_Set_Char_Size traffic in RenderCharGlyphImageCore can't stomp another handle's sizing. And FontObj fallback = *obj with setCharSize(&fallback) is a neat way to reuse the whole render path without touching the primary face's state.
  • Kerning across files returning 0 (same-face-only rule in the new LoadKerning) matches what a console would do between two different font files, and the tests pin it.
  • The debt-file honesty is good: the script bits are SDK-set-name-derived, not measured, and the primary-only answers of sceFontGetCharGlyphCode/sceFontGetFontGlyphsCount are recorded.

One thing to keep an eye on, no change requested: SystemFontBytes(fallback.path) is re-read from disk for every opened set, so a title that opens several multi-script sets loads one copy of each fallback file per set — the CJK .ttc substitutes are the heavy ones. The primary file already behaved this way, so it's consistent, but if a memory report ever comes in from a font-heavy title, a process-wide bytes cache keyed by path would be the lever.

The test coverage is the strong part: metrics, instances, kerning across files, rendered pixels for each script, and the no-Hangul-in-JP_AR negative case, with the fail-on-main check to prove the tests actually exercise the new behavior.

@HQasper

HQasper commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Manual check of the files the overlap report could not compare. #6044 moves GuestSystemFont.cpp to core/libs/tests/media/; a merge carries this change's test lines to the new path. #5021, #5925, #6788, #6924, #6946, #6947, #7332 and #7417 share only docs/user/USAGE.md and none edits the system fonts section; merged directly with this branch, each conflicts only where it already conflicts with main. Related: #7730 also changes sceFontOpenFontSet (a warning when a set's primary file is missing) and GuestSystemFont.cpp. The two merge without conflicts and the merged function keeps both; whichever lands second should rerun guest_system_font. Depends on: none.

@wachi35676

Copy link
Copy Markdown
Contributor

Windows 11, Ryzen 5 9600X, WinLibs GCC 15.2.0 (UCRT), Release, BUILD_TESTING=ON. Head bff194647 merged onto main eb75006.

  • On Windows, guest_system_font, guest_font, guest_font_writing_line and the three font_face_lifetime* tests pass.
  • Negative control: with the six libSceFont sources put back to main, guest_system_font aborts with System font check failed at line 132, as the description says.

I compared the code with the shadPS4 file the debt cites. It links main; I read it at b45b289. It does not support all of the debt's wording:

  • File order. The debt says the order comes from shadPS4. shadPS4's fallback_paths (lines 1995-2013) are: Latin (when the primary file is not Latin), Arabic, Thai, Japanese, Hangul, simplified Chinese. FallbackFamilies uses Vietnamese, Thai, Chinese if (scripts & 0x88) == 0x88, Japanese, Chinese, Hangul, Arabic. So Arabic is first in shadPS4 and last here.
    • For ..._GBCJK (0x1807AC44), this PR puts simplified Chinese before Japanese, but shadPS4 tries Japanese first (needs_jppro and needs_cngb are both true for tag 0xAC).
    • Either order may be right on a console, but the debt should call it this PR's choice, not shadPS4's.
  • Vietnamese. shadPS4 opens no Vietnamese file for any set. The low-byte 0x10 → Vietnamese rule is this PR's inference from the set names, for example 0x18080454 FONTSET_SST_STD_VIETNAMESE_JP. In shadPS4, the same low byte (0x53/0x54/0x55/0x57) is the "SEA weight" that IsThaiSeaWeightTag combines with the script tag to decide Thai.
  • Hangul light weight. shadPS4 maps SCE-EXT-HANGUL-L.OTF to SCEPS4Yoongd-Light.otf (line 440), but the new FAMILY_FILES row uses SCEPS4Yoongd-Medium.otf for the light weight. A light set with the console's Light file present will open Medium. The debt names only the Medium and Bold files.

AI-assisted: yes (Claude Code); results above were run on this machine.

@vittoriosalvadore

vittoriosalvadore commented Oct 20, 2026 •

Copy link
Copy Markdown

@wachi35676 @HQasper Thank you for the review and implementation. HQasper/AnyPS5#5 corrects the Hangul Light mapping and debt attribution, with a regression test. All six focused Font tests pass locally with zero skips. Ready for your review and integration.

@oneandonlydean
oneandonlydean merged commit 083a3be into boykopovar:main Oct 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants