forked from microsoft/react-native-macos
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reimplement Android lineHeight positioning/determination (facebook#47271
) Summary: Pull Request resolved: facebook#47271 Let's keep the recent goals of centering (instead of arbitrary prioritizing ascent), ala spec, and make some changes to allow overlapping interior line-boxes, and make the implementation a lot simpler, instead of the cruft it has been accumulating. The new simple versions is implemented as the only `CustomLineHeightSpan`. This replaces the code used when `enableAndroidLineHeightCentering` is enabled (which is now the default). Legacy path is renamed to `LegacyLineHeightSpan`, slated to be deleted if rollout goes well. We cannot yet cause text to overflow the bounds of the underlying TextView until potentially large later work related to ReactTextView reimplementation. There's a somewhat arbitrary choice here, when rounding, to whether we ceil ascent vs descent when pixels don't evenly split. This does result in a visual difference, and for sake of avoiding breakage of screenshots, I left the same choice as before. Changelog: [Android][Fixed] - Reimplement Android lineHeight positioning/determination Reviewed By: javache Differential Revision: D64716557
- Loading branch information
1 parent
9a8459d
commit 505830e
Showing
10 changed files
with
132 additions
and
226 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
...Android/src/main/java/com/facebook/react/views/text/internal/span/LegacyLineHeightSpan.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.facebook.react.views.text.internal.span | ||
|
||
import android.graphics.Paint.FontMetricsInt | ||
import android.text.style.LineHeightSpan | ||
import kotlin.math.ceil | ||
import kotlin.math.floor | ||
import kotlin.math.min | ||
|
||
/** | ||
* We use a custom [LineHeightSpan], because `lineSpacingExtra` is broken. Details here: | ||
* https://github.com/facebook/react-native/issues/7546 | ||
*/ | ||
public class LegacyLineHeightSpan(height: Float) : LineHeightSpan, ReactSpan { | ||
public val lineHeight: Int = ceil(height.toDouble()).toInt() | ||
|
||
public override fun chooseHeight( | ||
text: CharSequence?, | ||
start: Int, | ||
end: Int, | ||
spanstartv: Int, | ||
v: Int, | ||
fm: FontMetricsInt, | ||
) { | ||
// This is more complicated that I wanted it to be. You can find a good explanation of what the | ||
// FontMetrics mean here: http://stackoverflow.com/questions/27631736. | ||
// The general solution is that if there's not enough height to show the full line height, we | ||
// will prioritize in this order: descent, ascent, bottom, top | ||
|
||
if (fm.descent > lineHeight) { | ||
// Show as much descent as possible | ||
fm.descent = min(lineHeight.toDouble(), fm.descent.toDouble()).toInt() | ||
fm.bottom = fm.descent | ||
fm.ascent = 0 | ||
fm.top = fm.ascent | ||
} else if (-fm.ascent + fm.descent > lineHeight) { | ||
// Show all descent, and as much ascent as possible | ||
fm.bottom = fm.descent | ||
fm.ascent = -lineHeight + fm.descent | ||
fm.top = fm.ascent | ||
} else if (-fm.ascent + fm.bottom > lineHeight) { | ||
// Show all ascent, descent, as much bottom as possible | ||
fm.top = fm.ascent | ||
fm.bottom = fm.ascent + lineHeight | ||
} else if (-fm.top + fm.bottom > lineHeight) { | ||
// Show all ascent, descent, bottom, as much top as possible | ||
fm.top = fm.bottom - lineHeight | ||
} else { | ||
// Show proportionally additional ascent / top & descent / bottom | ||
val additional = lineHeight - (-fm.top + fm.bottom) | ||
|
||
// Round up for the negative values and down for the positive values (arbitrary choice) | ||
// So that bottom - top equals additional even if it's an odd number. | ||
val top = (fm.top - ceil(additional / 2.0f)).toInt() | ||
val bottom = (fm.bottom + floor(additional / 2.0f)).toInt() | ||
|
||
fm.top = top | ||
fm.ascent = top | ||
fm.descent = bottom | ||
fm.bottom = bottom | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.