Android Text: Fix `letterSpacing` rendering when `fontSize` changes (#22993)

Summary:
If you set `letterSpacing` on an outer text and then set `fontSize` on an inner text, the wrong `letterSpacing` will be rendered.

Here's an example:

```
<Text style={{ fontSize: 10, letterSpacing: 10 }}>
  <Text style={{ fontSize: 20 }}>Some text</Text>
</Text>
```

`fontSize` affects letter spacing. In this case, the bug is that setting `fontSize` to `20` doesn't cause the letter spacing to be recalculated.

Notice that the logic for applying letter spacing only applies it if the node has a different value for `getEffectiveLetterSpacing()` than its parent. The problem is that `getEffectiveLetterSpacing()` doesn't represent the final letter spacing value -- it doesn't take `fontSize` into account. Consequently, it sometimes incorrectly skips applying letter spacing as illustrated above.

The fix is to ensure `getEffectiveLetterSpacing()` represents the final rendered letter spacing value. To do this, some of the letter spacing calculation code was moved from `CustomLetterSpacingSpan` to `getEffectiveLetterSpacing()`.
Pull Request resolved: https://github.com/facebook/react-native/pull/22993

Differential Revision: D13671505

Pulled By: cpojer

fbshipit-source-id: 400f36d3fd71ab7cb6cba8508baa71f2973f8f0e
This commit is contained in:
Adam Comella 2019-01-16 05:30:50 -08:00 коммит произвёл Facebook Github Bot
Родитель e6057095ad
Коммит 0db0d263ac
3 изменённых файлов: 7 добавлений и 5 удалений

Просмотреть файл

@ -42,10 +42,8 @@ public class CustomLetterSpacingSpan extends MetricAffectingSpan {
}
private void apply(TextPaint paint) {
// mLetterSpacing and paint.getTextSize() are both in pixels,
// yielding an accurate em value.
if (!Float.isNaN(mLetterSpacing)) {
paint.setLetterSpacing(mLetterSpacing / paint.getTextSize());
paint.setLetterSpacing(mLetterSpacing);
}
}
}

Просмотреть файл

@ -121,9 +121,13 @@ public class TextAttributes {
return Float.NaN;
}
return mAllowFontScaling
float letterSpacingPixels = mAllowFontScaling
? PixelUtil.toPixelFromSP(mLetterSpacing)
: PixelUtil.toPixelFromDIP(mLetterSpacing);
// `letterSpacingPixels` and `getEffectiveFontSize` are both in pixels,
// yielding an accurate em value.
return letterSpacingPixels / getEffectiveFontSize();
}
public String toString() {

Просмотреть файл

@ -667,7 +667,7 @@ public class ReactEditText extends EditText {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing();
if (!Float.isNaN(effectiveLetterSpacing)) {
setLetterSpacing(effectiveLetterSpacing / getTextSize());
setLetterSpacing(effectiveLetterSpacing);
}
}
}