Fix custom font weight rendering heaviest face on iOS Fabric#57483
Fix custom font weight rendering heaviest face on iOS Fabric#57483jensdev wants to merge 1 commit into
Conversation
|
Hi @jensdev! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
Summary:
On the New Architecture (Fabric), a custom font referenced by its PostScript / full font name (e.g.
fontFamily: "Foo-Medium") combined with an explicit non-regularfontWeightrenders at the heaviest available face (bold/black) instead of the requested weight. This is an iOS-only regression introduced in 0.83; 0.82 was correct. Android is unaffected.Root cause. In
RCTFontUtils.mm,RCTFontWithFontProperties()handles the case where the givenfontFamilyis actually a font name rather than a family name (fontNames.count == 0) and resolves the effective weight with:fontWeight = (fontWeight != 0.0) ?: RCTGetFontWeight(font);fontWeightis aUIFontWeight(adouble: Regular = 0.0, Medium = 0.23, Bold = 0.4, Black = 0.62). The Objective-C "Elvis" operatorA ?: Bevaluates toAitself whenAis truthy — and hereAis the comparison(fontWeight != 0.0), aBOOL. So whenever a weight was set (e.g. 0.23),fontWeightwas reassigned to1.0(heavier than Black), and the subsequent "closest weight in the family" search always picked the heaviest face.This was introduced by the automated implicit-bool-conversion sweep in #53591 (D81571883), which rewrote the original correct line
fontWeight ?: RCTGetFontWeight(font)into(fontWeight != 0.0) ?: …. Making the truthiness check explicit is fine as a condition, but with?:the left-hand side is also the returned value, so the numeric weight got replaced by the boolean.Fix.
fontWeight = (fontWeight != 0.0) ? fontWeight : RCTGetFontWeight(font);For a
double,(A != 0.0) ? A : Bis exactly equivalent to the originalA ?: B, so this restores the 0.81/0.82 behavior while keeping the explicit!= 0.0form used elsewhere in the file. The no-weight case is unchanged:RCTResolveFontPropertiesfills an unspecified weight withUIFontWeightRegular(0.0), so the weight is still inferred from the font name viaRCTGetFontWeight(font)in that case. The legacy (Paper) path inReact/Views/RCTFont.mmuses a different construct and is not affected — consistent with his only reproducing on the New Architecture.Changelog:
[iOS] [Fixed] - Custom fonts with an explicit fontWeight no longer render at the heaviest weight on the New Architecture
Test Plan:
Fixes #54934.
New Architecture, iOS, with a custom font bundled and referenced by its PostScript name,
e.g.
<Text style={{ fontFamily: 'Foo-Medium', fontWeight: '500' }}>:main(before fix)fontWeighton 0.83After this change the text renders at the requested weight on both the old and new architecture.