-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Android] Fix: incorrect line-height calculation #17952
Conversation
Round the division by 2 result up and down so that the sum is still the same as the lineheight when the additional variable happens to be odd. Added test test to see that bottom-top is still equals the line height when it's odd. This test does not care which value the implementation chooses to round up or down as long as the sum is correct.
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up 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 the corporate CLA signed. If you have received this in error or have any questions, please contact us at [email protected]. Thanks! |
Generated by 🚫 dangerJS |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Not sure how I can actually test these changes in a project. Is there some quick and dirty way I can just replace the modified file and deploy it on my phone in an existing project; without having to do a full build? Making a full build would be hard, since I'm having a lot of issues with getting the full build env running on my linux laptop. |
I tried using only floats, but it seems everything expects it to be integers, so I decided to use rounding instead and add the remainder to the negative values. |
@strindhaug I think the easiest way to test is copy your changes under node_modules and run ./gradlew installArchives in node_modules/react-native, then rebuild your app. |
You can probably also test in the example app RN Tester, you can run it with ./gradlew RNTester:android:app:installDebug. Pre-requisites to build from source are listed here http://facebook.github.io/react-native/docs/android-building-from-source.html. |
I finally figured it out! The multiline version were shorter than it should because apparently the top and bottom values are only used for the extra padding at the top and bottom, the ascent and descent is the ones that actually control the internal line height. Since in the last else section the desired line-height is larger than both the top+bottom and ascent+descent, it's safe to set the ascent and descent to the same values as top and bottom respectively. So that the resulting line-height actually matches the desired line-height: |
@strindhaug Awesome work, let me know if anything is unclear in the doc for building on linux, I'd like to make contributing as easy as possible. |
@facebook-github-bot shipit |
Something went wrong executing that command, @hramos could you take a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@janicduplessis is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
Summary: There seems to be a rounding error in the android code for line height, so that for some fonts and at some combinations of line height and font size the actual height of the elements seems to be slightly too short. I've identified one issue that I mentioned here facebook#10712 (comment) that could at least explain some of the problem. That when the line-height minus the original sum of the absolute value of top and bottom from the metrics, happens to be an odd number, the division by two causes a rounding error of 1, so that the actual line height is 1pt less than it should. The fix uses floating point division instead of integer division, and rounds (arbitrarily) the negative values up and the positive values down so that the total is still the correct for odd numbers. It turns out that only ascent and descent is used to give the actual line-height between lines in the same text-element. The top and bottom values are only used for padding the top and bottom of the text. So when the line-height is greater than the font size and the extra padding this PR sets the ascent and descent to the same value as the top and bottom respectively. I've renamed the shouldIncreaseAllMetricsProportionally test to evenLineHeightShouldIncreaseAllMetricsProportionally and added an extra assertion to check that bottom-top still equals the line height. Added another test oddLineHeightShouldAlsoWork that is similar but uses an odd number for the line height to test that it still works with odd numbers. This test only uses the sum of the values so that it's indifferent to what value the implementation chooses to round up or down. Improvement on facebook#16448 Fix line-height calculation on Android. | Before | After | | ------------- |-------------| | ![without fix](https://user-images.githubusercontent.com/2144849/36150230-4404a0cc-10c3-11e8-8880-4ab84339c741.png) | ![actual fix](https://user-images.githubusercontent.com/2144849/36156620-eb496d0e-10d7-11e8-8bd1-1cb536a38fbf.png) | (All three columns have font size 16 and lineHeight: 32. The first one is has fixed height 9*32, the second is 9 Text elements, the last is one text element with lots of text limited to 9 lines, so they should be the same height. ) Closes facebook#17952 Differential Revision: D6980333 Pulled By: hramos fbshipit-source-id: 0a501358cfbf7f139fca46056d0d972b1daf6ae3
@janicduplessis And the building from source by adding it to an existing project using all those changes in gradle, does seem to build react-native itself successfully without any error messages during build; but it fails to complete because react-native-sentry fails:
So either my build of the tag But I do find it suspicious that when I run
(Running I grepped the output to find all the missing packages:
Either I've missed some step to install these, or maybe I'm not supposed to run those gradle tasks? |
Summary: There seems to be a rounding error in the android code for line height, so that for some fonts and at some combinations of line height and font size the actual height of the elements seems to be slightly too short. I've identified one issue that I mentioned here facebook#10712 (comment) that could at least explain some of the problem. That when the line-height minus the original sum of the absolute value of top and bottom from the metrics, happens to be an odd number, the division by two causes a rounding error of 1, so that the actual line height is 1pt less than it should. The fix uses floating point division instead of integer division, and rounds (arbitrarily) the negative values up and the positive values down so that the total is still the correct for odd numbers. It turns out that only ascent and descent is used to give the actual line-height between lines in the same text-element. The top and bottom values are only used for padding the top and bottom of the text. So when the line-height is greater than the font size and the extra padding this PR sets the ascent and descent to the same value as the top and bottom respectively. I've renamed the shouldIncreaseAllMetricsProportionally test to evenLineHeightShouldIncreaseAllMetricsProportionally and added an extra assertion to check that bottom-top still equals the line height. Added another test oddLineHeightShouldAlsoWork that is similar but uses an odd number for the line height to test that it still works with odd numbers. This test only uses the sum of the values so that it's indifferent to what value the implementation chooses to round up or down. Improvement on facebook#16448 Fix line-height calculation on Android. | Before | After | | ------------- |-------------| | ![without fix](https://user-images.githubusercontent.com/2144849/36150230-4404a0cc-10c3-11e8-8880-4ab84339c741.png) | ![actual fix](https://user-images.githubusercontent.com/2144849/36156620-eb496d0e-10d7-11e8-8bd1-1cb536a38fbf.png) | (All three columns have font size 16 and lineHeight: 32. The first one is has fixed height 9*32, the second is 9 Text elements, the last is one text element with lots of text limited to 9 lines, so they should be the same height. ) Closes facebook#17952 Differential Revision: D6980333 Pulled By: hramos fbshipit-source-id: 0a501358cfbf7f139fca46056d0d972b1daf6ae3
Summary: There seems to be a rounding error in the android code for line height, so that for some fonts and at some combinations of line height and font size the actual height of the elements seems to be slightly too short. I've identified one issue that I mentioned here facebook#10712 (comment) that could at least explain some of the problem. That when the line-height minus the original sum of the absolute value of top and bottom from the metrics, happens to be an odd number, the division by two causes a rounding error of 1, so that the actual line height is 1pt less than it should. The fix uses floating point division instead of integer division, and rounds (arbitrarily) the negative values up and the positive values down so that the total is still the correct for odd numbers. It turns out that only ascent and descent is used to give the actual line-height between lines in the same text-element. The top and bottom values are only used for padding the top and bottom of the text. So when the line-height is greater than the font size and the extra padding this PR sets the ascent and descent to the same value as the top and bottom respectively. I've renamed the shouldIncreaseAllMetricsProportionally test to evenLineHeightShouldIncreaseAllMetricsProportionally and added an extra assertion to check that bottom-top still equals the line height. Added another test oddLineHeightShouldAlsoWork that is similar but uses an odd number for the line height to test that it still works with odd numbers. This test only uses the sum of the values so that it's indifferent to what value the implementation chooses to round up or down. Improvement on facebook#16448 Fix line-height calculation on Android. | Before | After | | ------------- |-------------| | ![without fix](https://user-images.githubusercontent.com/2144849/36150230-4404a0cc-10c3-11e8-8880-4ab84339c741.png) | ![actual fix](https://user-images.githubusercontent.com/2144849/36156620-eb496d0e-10d7-11e8-8bd1-1cb536a38fbf.png) | (All three columns have font size 16 and lineHeight: 32. The first one is has fixed height 9*32, the second is 9 Text elements, the last is one text element with lots of text limited to 9 lines, so they should be the same height. ) Closes facebook#17952 Differential Revision: D6980333 Pulled By: hramos fbshipit-source-id: 0a501358cfbf7f139fca46056d0d972b1daf6ae3
Summary: This sync includes the following changes: - **[b5c6dd2de](facebook/react@b5c6dd2de )**: Don't use Spread in DevTools Injection (#18277) //<Sebastian Markbåge>// - **[a463fef31](facebook/react@a463fef31 )**: Revert "[React Native] Add getInspectorDataForViewAtPoint (#18233)" //<Sebastian Markbage>// - **[dc7eedae3](facebook/react@dc7eedae3 )**: Encode server rendered host components as array tuples (#18273) //<Sebastian Markbåge>// - **[bf351089a](facebook/react@bf351089a )**: [React Native] Add getInspectorDataForViewAtPoint (#18233) //<Ricky>// - **[99d737186](facebook/react@99d737186 )**: [Flight] Split Streaming from Relay Implemenation (#18260) //<Sebastian Markbåge>// - **[160505b0c](facebook/react@160505b0c )**: ReactDOM.useEvent: Add more scaffolding for useEvent hook (#18271) //<Dominic Gannaway>// - **[526c12f49](facebook/react@526c12f49 )**: Enable enableProfilerCommitHooks flag for FB (#18230) //<Brian Vaughn>// - **[29534252a](facebook/react@29534252a )**: ReactDOM.useEvent add flag and entry point (#18267) //<Dominic Gannaway>// - **[704c8b011](facebook/react@704c8b011 )**: Fix Flow type for AnyNativeEvent (#18266) //<Dominic Gannaway>// - **[bdc5cc463](facebook/react@bdc5cc463 )**: Add Relay Flight Build (#18242) //<Sebastian Markbåge>// - **[7a1691cdf](facebook/react@7a1691cdf )**: Refactor Host Config Infra (getting rid of .inline*.js) (#18240) //<Sebastian Markbåge>// - **[238b57f0f](facebook/react@238b57f0f )**: [Blocks] Make it possible to have lazy initialized and lazy loaded Blocks (#18220) //<Sebastian Markbåge>// - **[235a6c4af](facebook/react@235a6c4af )**: Bugfix: Dropped effects in Legacy Mode Suspense (#18238) //<Andrew Clark>// - **[562cf013d](facebook/react@562cf013d )**: Add a flag to disable module pattern components (#18133) //<Dan Abramov>// - **[115cd12d9](facebook/react@115cd12d9 )**: Add test run that uses www feature flags (#18234) //<Andrew Clark>// - **[4027f2a3b](facebook/react@4027f2a3b )**: Break up require/import statements in strings (#18222) //<Christoph Nakazawa>// - **[024a76431](facebook/react@024a76431 )**: Implemented Profiler onCommit() and onPostCommit() hooks (#17910) //<Brian Vaughn>// - **[d35f8a581](facebook/react@d35f8a581 )**: feat: honor displayName of context types (#18224) //<Brian Vaughn>// - **[3ee812e6b](facebook/react@3ee812e6b )**: Revert "feat: honor displayName of context types (#18035)" (#18223) //<Dominic Gannaway>// - **[6a0efddd8](facebook/react@6a0efddd8 )**: Modern Event System: export internal FB flag for testing (#18221) //<Dominic Gannaway>// - **[fa03206ee](facebook/react@fa03206ee )**: Remove _ctor field from Lazy components (#18217) //<Sebastian Markbåge>// - **[2fe0fbb05](facebook/react@2fe0fbb05 )**: Use accumulateTwoPhaseDispatchesSingle directly (#18203) //<Dominic Gannaway>// - **[503fd82b4](facebook/react@503fd82b4 )**: Modern Event System: Add support for internal FB Primer (#18210) //<Dominic Gannaway>// - **[45c172d94](facebook/react@45c172d94 )**: feat: honor displayName of context types (#18035) //<Brian Vaughn>// - **[ec652f4da](facebook/react@ec652f4da )**: Bugfix: Expired partial tree infinite loops (#17949) //<Andrew Clark>// - **[d2158d6cc](facebook/react@d2158d6cc )**: Fix flow types (#18204) //<Brian Vaughn>// - **[7e83af17c](facebook/react@7e83af17c )**: Put React.jsx and React.jsxDEV behind experimental build (#18023) //<Luna Ruan>// - **[8cb2fb21e](facebook/react@8cb2fb21e )**: Refine isFiberSuspenseAndTimedOut (#18184) //<Dominic Gannaway>// - **[62861bbcc](facebook/react@62861bbcc )**: More event system cleanup and scaffolding (#18179) //<Dominic Gannaway>// - **[8ccfce460](facebook/react@8ccfce460 )**: Only use Rollup's CommonJS plugin for "react-art" (#18186) //<Sebastian Markbåge>// - **[c26506a7d](facebook/react@c26506a7d )**: Update react-shallow-renderer from 16.12.0 to 16.13.0 (#18185) //<Minh Nguyen>// - **[26aa1987c](facebook/react@26aa1987c )**: [Native] Enable and remove targetAsInstance feature flag. (#18182) //<Eli White>// - **[4469700bb](facebook/react@4469700bb )**: Change ReactVersion from CJS to ES module (#18181) //<Sebastian Markbåge>// - **[58eedbb02](facebook/react@58eedbb02 )**: Check in a forked version of object-assign only for UMD builds (#18180) //<Sebastian Markbåge>// - **[053347e6b](facebook/react@053347e6b )**: react-test-renderer: improve findByType() error message (#17439) //<Henry Q. Dineen>// - **[4ee592e95](facebook/react@4ee592e95 )**: Add an early invariant to debug a mystery crash (#18159) //<Dan Abramov>// - **[7ea4e4111](facebook/react@7ea4e4111 )**: Fix typo in warning text (#18103) //<Sophie Alpert>// - **[79a25125b](facebook/react@79a25125b )**: feat: add recommended config eslint rule (#14762) //<Simen Bekkhus>// - **[ae60caacf](facebook/react@ae60caacf )**: [Fabric] Fix targetAsInstance dispatchEvent "cannot read property of null" (#18156) //<Joshua Gross>// - **[d72700ff5](facebook/react@d72700ff5 )**: Remove runtime dependency on prop-types (#18127) //<Dan Abramov>// - **[549e41883](facebook/react@549e41883 )**: Move remaining things to named exports (#18165) //<Sebastian Markbåge>// - **[739f20bed](facebook/react@739f20bed )**: Remove Node shallow builds (#18157) //<Sebastian Markbåge>// - **[3e809bf5d](facebook/react@3e809bf5d )**: Convert React Native builds to named exports (#18136) //<Sebastian Markbåge>// - **[869dbda72](facebook/react@869dbda72 )**: Don't build shallow renderer for FB (#18153) //<Dan Abramov>// - **[293878e07](facebook/react@293878e07 )**: Replace ReactShallowRenderer with a dependency (#18144) //<Minh Nguyen>// - **[b4e314891](facebook/react@b4e314891 )**: Remove unused flag (#18132) //<Dan Abramov>// - **[849e8328b](facebook/react@849e8328b )**: Remove unnecessary warnings (#18135) //<Dan Abramov>// - **[f9c0a4544](facebook/react@f9c0a4544 )**: Convert the rest of react-dom and react-test-renderer to Named Exports (#18145) //<Sebastian Markbåge>// - **[c1c5499cc](facebook/react@c1c5499cc )**: update version numbers for 16.13 (#18143) //<Sunil Pai>// - **[e1c7e651f](facebook/react@e1c7e651f )**: Update ReactDebugHooks to handle composite hooks (#18130) //<Brian Vaughn>// - **[d28bd2994](facebook/react@d28bd2994 )**: remove OSS testing builds (#18138) //<Sunil Pai>// - **[8e13e770e](facebook/react@8e13e770e )**: Remove /testing entry point from 'react' package (#18137) //<Sebastian Markbåge>// - **[60016c448](facebook/react@60016c448 )**: Export React as Named Exports instead of CommonJS (#18106) //<Sebastian Markbåge>// - **[8d7535e54](facebook/react@8d7535e54 )**: Add nolint to FB bundle headers (#18126) //<Dominic Gannaway>// - **[bf13d3e3c](facebook/react@bf13d3e3c )**: [eslint-plugin-react-hooks] Fix cyclic caching for loops containing a… (#16853) //<Moji Izadmehr>// - **[501a78881](facebook/react@501a78881 )**: runAllPassiveEffectDestroysBeforeCreates's feature flag description typo fixed (#18115) //<adasq>// - **[09348798a](facebook/react@09348798a )**: Codemod to import * as React from "react"; (#18102) //<Sebastian Markbåge>// - **[78e816032](facebook/react@78e816032 )**: Don't warn about unmounted updates if pending passive unmount (#18096) //<Brian Vaughn>// - **[2c4221ce8](facebook/react@2c4221ce8 )**: Change string refs in function component message (#18031) //<Sebastian Markbåge>// - **[65bbda7f1](facebook/react@65bbda7f1 )**: Rename Chunks API to Blocks (#18086) //<Sebastian Markbåge>// - **[8b596e00a](facebook/react@8b596e00a )**: Remove unused arguments in the reconciler (#18092) //<Dan Abramov>// - **[5de5b6150](facebook/react@5de5b6150 )**: Bugfix: `memo` drops lower pri updates on bail out (#18091) //<Andrew Clark>// - **[abfbae02a](facebook/react@abfbae02a )**: Update Rollup version to 1.19.4 and fix breaking changes (#15037) //<Kunuk Nykjær>// - **[b789060dc](facebook/react@b789060dc )**: Feature Flag for React.jsx` "spreading a key to jsx" warning (#18074) //<Sunil Pai>// - **[3f85d53ca](facebook/react@3f85d53ca )**: Further pre-requisite changes to plugin event system (#18083) //<Dominic Gannaway>// - **[ea6ed3dbb](facebook/react@ea6ed3dbb )**: Warn for update on different component in render (#17099) //<Andrew Clark>// - **[085d02133](facebook/react@085d02133 )**: [Native] Migrate focus/blur to call TextInputState with the host component (#18068) //<Eli White>// - **[1000f6135](facebook/react@1000f6135 )**: Add container to event listener signature (#18075) //<Dominic Gannaway>// - **[a12dd52a4](facebook/react@a12dd52a4 )**: Don't build some packages for WWW (#18078) //<Dan Abramov>// - **[2512c309e](facebook/react@2512c309e )**: Remove Flare bundles from build (#18077) //<Dominic Gannaway>// - **[4912ba31e](facebook/react@4912ba31e )**: Add modern event system flag + rename legacy plugin module (#18073) //<Dominic Gannaway>// - **[4d9f85006](facebook/react@4d9f85006 )**: Re-throw errors thrown by the renderer at the root in the complete phase (#18029) //<Andrew Clark>// - **[14afeb103](facebook/react@14afeb103 )**: Added missing feature flag //<Brian Vaughn>// - **[691096c95](facebook/react@691096c95 )**: Split recent passive effects changes into 2 flags (#18030) //<Brian Vaughn>// - **[56d8a73af](facebook/react@56d8a73af )**: [www] Disable Scheduler `timeout` w/ dynamic flag (#18069) //<Andrew Clark>// - **[d533229fb](facebook/react@d533229fb )**: Fix Prettier //<Dan Abramov>// - **[56a8c3532](facebook/react@56a8c3532 )**: [email protected] //<Dan Abramov>// - **[93a229bab](facebook/react@93a229bab )**: Update eslint rule exhaustive deps to use new suggestions feature (#17385) //<Will Douglas>// - **[9def56ec0](facebook/react@9def56ec0 )**: Refactor DOM plugin system to single module (#18025) //<Dominic Gannaway>// - **[2d6be757d](facebook/react@2d6be757d )**: [Native] Delete NativeComponent and NativeMethodsMixin (#18036) //<Eli White>// - **[d4f2b03](facebook/react@d4f2b0379 )**: Add Auto Import to Babel Plugin (#16626) //<Luna Ruan>// - **[8777b44e9](facebook/react@8777b44e9 )**: Add Modern WWW build (#18028) //<Dan Abramov>// - **[a607ea4c4](facebook/react@a607ea4c4 )**: Remove getIsHydrating (#18019) //<Dan Abramov>// - **[f7278034d](facebook/react@f7278034d )**: Flush all passive destroy fns before calling create fns (#17947) //<Brian Vaughn>// - **[529e58ab0](facebook/react@529e58ab0 )**: Remove legacy www config from Rollup build (#18016) //<Dominic Gannaway>// - **[42918f40a](facebook/react@42918f40a )**: Change build from babylon to babel (#18015) //<Dominic Gannaway>// - **[df5faddcc](facebook/react@df5faddcc )**: Refactor commitPlacement to recursively insert nodes (#17996) //<Dominic Gannaway>// - **[517de74b0](facebook/react@517de74b0 )**: Tweak comment wording (#18007) //<Dan Abramov>// - **[b63cb6f6c](facebook/react@b63cb6f6c )**: Update ReactFiberExpirationTime.js (#17825) //<haseeb>// - **[89c6042df](facebook/react@89c6042df )**: fix: typo in test (#18005) //<Jesse Katsumata>// - **[4f71f25a3](facebook/react@4f71f25a3 )**: Re-enable shorthand CSS property collision warning (#18002) //<Sophie Alpert>// - **[c55c34e46](facebook/react@c55c34e46 )**: Move React Map child check to behind flags or __DEV__ (#17995) //<Dominic Gannaway>// - **[3f814e758](facebook/react@3f814e758 )**: Fix Flow type for React Native (#17992) //<Dan Abramov>// - **[256d78d11](facebook/react@256d78d11 )**: Add feature flag for removing children Map support (#17990) //<Dominic Gannaway>// - **[9dba218d9](facebook/react@9dba218d9 )**: [Mock Scheduler] Mimic browser's advanceTime (#17967) //<Andrew Clark>// - **[d6e08fe0a](facebook/react@d6e08fe0a )**: Remove Suspense priority warning (#17971) //<Dan Abramov>// - **[812277dab](facebook/react@812277dab )**: Fix onMouseEnter is fired on disabled buttons (#17675) //<Alfredo Granja>// - **[3e9251d60](facebook/react@3e9251d60 )**: make testing builds for React/ReactDOM (#17915) //<Sunil Pai>// - **[ace9e8134](facebook/react@ace9e8134 )**: Simplify Continuous Hydration Targets (#17952) //<Sebastian Markbåge>// - **[7df32c4c8](facebook/react@7df32c4c8 )**: Flush `useEffect` clean up functions in the passive effects phase (#17925) //<Brian Vaughn>// - **[434770c3b](facebook/react@434770c3b )**: Add beforeRemoveInstance method to ReactNoop (#17959) //<Dominic Gannaway>// - **[6ae2c33a7](facebook/react@6ae2c33a7 )**: StrictMode should call sCU twice in DEV (#17942) //<Brian Vaughn>// - **[9dbe1c54d](facebook/react@9dbe1c54d )**: Revert "Bugfix: Expiring a partially completed tree (#17926)" (#17941) //<Andrew Clark>// - **[b2382a715](facebook/react@b2382a715 )**: Add ReactDOM.unstable_renderSubtreeIntoContainer warning flag (#17936) //<Dominic Gannaway>// - **[01974a867](facebook/react@01974a867 )**: Bugfix: Expiring a partially completed tree (#17926) //<Andrew Clark>// Changelog: [General][Changed] - React Native sync for revisions 241c446...b5c6dd2 Reviewed By: gaearon Differential Revision: D20347361 fbshipit-source-id: e9e6282474ab6471585e8e7fb6ea8518aa48390d
Motivation
There seems to be a rounding error in the android code for line height, so that for some fonts and at some combinations of line height and font size the actual height of the elements seems to be slightly too short.
I've identified one issue that I mentioned here #10712 (comment) that could at least explain some of the problem. That when the line-height minus the original sum of the absolute value of top and bottom from the metrics, happens to be an odd number, the division by two causes a rounding error of 1, so that the actual line height is 1pt less than it should.
The fix uses floating point division instead of integer division, and rounds (arbitrarily) the negative values up and the positive values down so that the total is still the correct for odd numbers.
It turns out that only ascent and descent is used to give the actual line-height between lines in the same text-element. The top and bottom values are only used for padding the top and bottom of the text. So when the line-height is greater than the font size and the extra padding this PR sets the ascent and descent to the same value as the top and bottom respectively.
Test Plan
I've renamed the shouldIncreaseAllMetricsProportionally test to evenLineHeightShouldIncreaseAllMetricsProportionally and added an extra assertion to check that bottom-top still equals the line height.
Added another test oddLineHeightShouldAlsoWork that is similar but uses an odd number for the line height to test that it still works with odd numbers. This test only uses the sum of the values so that it's indifferent to what value the implementation chooses to round up or down.
Related PRs
Improvement on #16448
Release Notes
Fix line-height calculation on Android.
(All three columns have font size 16 and lineHeight: 32. The first one is has fixed height 9*32, the second is 9 Text elements, the last is one text element with lots of text limited to 9 lines, so they should be the same height. )