Skip to content

Apply the bold text accessibility weight to Skia font fallback - #3325

Open
kohei.okamoto (okaponta) wants to merge 2 commits into
JetBrains:jb-mainfrom
okaponta:fix/cmp-10193-ios-bold-cjk-fallback
Open

Apply the bold text accessibility weight to Skia font fallback#3325
kohei.okamoto (okaponta) wants to merge 2 commits into
JetBrains:jb-mainfrom
okaponta:fix/cmp-10193-ios-bold-cjk-fallback

Conversation

@okaponta

@okaponta kohei.okamoto (okaponta) commented Aug 20, 2026

Copy link
Copy Markdown

Fixes https://youtrack.jetbrains.com/issue/CMP-10193

On iOS, IOSResolveInterceptor raises the requested font weight for the "Bold Text" accessibility setting, but only inside FontFamilyResolver. ComputedStyle.toSkTextStyle() assigned the intercepted typeface while storing the raw weight in SkTextStyle.fontStyle, leaving the two out of sync.

Latin glyphs are taken from the typeface and render bold. CJK glyphs are not covered by .AppleSystemUIFont, so they go through Skia's font fallback, which matches on fontStyle — and therefore picked a regular-weight face such as Hiragino Sans W3.

This applies the same interception to the weight stored in fontStyle, so fallback faces are matched at the same weight as the typeface. Platforms whose interceptor is a no-op are unaffected.

Testing

Added PlatformInterceptedFontWeightTest for the new seam. :compose:ui:ui-text:desktopTest and :compose:ui:ui-skiko:desktopTest pass locally.

The rendered result is not covered by any test. IOSResolveInterceptor reads UIAccessibilityIsBoldTextEnabled() once at initialisation, so a test cannot toggle the setting, and CI simulators run with it off — making it testable would need the interceptor to become injectable, which felt out of scope here. I also don't have an iOS environment to check it by hand. This should be tested by QA.

Release Notes

Fixes - iOS

  • Fixed the system "Bold Text" accessibility setting not being applied to CJK characters when using FontFamily.Default

Google CLA

Signed

@google-cla

google-cla Bot commented Aug 20, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

The iOS "Bold Text" accessibility setting is implemented by
IOSResolveInterceptor, which raises the requested font weight by 200.
That interception happens inside FontFamilyResolver, so only the
resolved typeface reflects it.

ComputedStyle.toSkTextStyle() stored the raw FontWeight in
SkTextStyle.fontStyle while assigning the intercepted typeface, leaving
the two out of sync. Latin glyphs are taken from the typeface and render
bold, but CJK glyphs are not covered by .AppleSystemUIFont and go
through Skia's font fallback, which matches on fontStyle. The fallback
therefore picked a regular-weight face such as Hiragino Sans W3 and the
setting appeared to have no effect on CJK text.

Expose the resolver's intercepted weight and use it for the weight
stored in the Skia text style, so fallback faces are matched at the same
weight as the primary typeface. The fontWeight == null case is covered
too, since the typeface is resolved from FontWeight.Normal and is
intercepted as well.

Platforms whose interceptor is a no-op are unaffected: both
SkFontStyle.NORMAL and SkFontStyle.ITALIC already carry weight 400, so
withWeight(400) is a no-op there.
@okaponta
kohei.okamoto (okaponta) force-pushed the fix/cmp-10193-ios-bold-cjk-fallback branch from 316857a to c95207b Compare August 20, 2026 15:51
@okaponta

Copy link
Copy Markdown
Author

The Desktop failure looks unrelated to this change — `DialogWindowV2StateTest and doesn't touch text or fonts.
It's the only failure out of 771 tests, and every other job including all the iOS ones is green.

Could you re-run that job when you get a chance?

@okaponta

Copy link
Copy Markdown
Author

Thanks for the re-run! It failed on a different set of tests this time — DialogWindowV2Test timing out after RenderException: Cannot create Linux GL context — so the Desktop job looks environmental rather than related to this change. Everything else, including all the iOS jobs is green.

Would it be possible to merge this?

@mazunin-v-jb

Copy link
Copy Markdown

Hi kohei.okamoto (@okaponta)!
Please make sure that your PR is following the guidelines
Actually, changes in the commonCode are not allowed here.

If you want this change to be accepted, please make sure to do the changes (which touch the commonCode) in the AOSP project first or rewrite these without changing the common code here.

@okaponta

Copy link
Copy Markdown
Author

Thanks for the review and the pointer!
I've re-read the guidelines and understand that common code changes have to go through AOSP.
I'll rework this without touching the common code.

Contributions that touch the common code of this fork have to go through
the AndroidX repository first, so the previous commit's accessor on
FontFamilyResolverImpl is not acceptable here.

Read the platform interceptor directly from nonAndroidMain instead. This
is equivalent: createPlatformResolveInterceptor() is what
createPlatformFontFamilyResolver() builds the resolver with, and on iOS
it returns the same object every time.

The interceptor can no longer be substituted per resolver, so the unit
test that injected a fake one is replaced by a desktop test asserting
that a platform without an interceptor leaves the weight untouched,
which is the property that keeps desktop and web unaffected.
@okaponta

Copy link
Copy Markdown
Author

Rewrote it without touching common code — the seam is now in ui-text/nonAndroidMain.
Could you take another look?

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