// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react.views.text;
import android.graphics.Paint;
import android.text.style.LineHeightSpan;
/**
* We use a custom {@link LineHeightSpan}, because `lineSpacingExtra` is broken. Details here:
* https://github.com/facebook/react-native/issues/7546
*/
public class CustomLineHeightSpan implements LineHeightSpan {
private final int mHeight;
CustomLineHeightSpan(float height) {
this.mHeight = (int) Math.ceil(height);
}
@Override
public void chooseHeight(
CharSequence text,
int start,
int end,
int spanstartv,
int v,
Paint.FontMetricsInt fm) {
// 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: ascent, descent, bottom, top
if (-fm.ascent > mHeight) {
// Show as much ascent as possible
fm.top = fm.ascent = -mHeight;
fm.bottom = fm.descent = 0;
} else if (-fm.ascent + fm.descent > mHeight) {
// Show all ascent, and as much descent as possible
fm.top = fm.ascent;
fm.bottom = fm.descent = mHeight + fm.ascent;
} else if (-fm.ascent + fm.bottom > mHeight) {
// Show all ascent, descent, as much bottom as possible
fm.top = fm.ascent;
fm.bottom = fm.ascent + mHeight;
} else if (-fm.top + fm.bottom > mHeight) {
// Show all ascent, descent, bottom, as much top as possible
fm.top = fm.bottom - mHeight;
} else {
// Show proportionally additional ascent and top
final int additional = mHeight - (-fm.top + fm.bottom);
fm.top -= additional;
fm.ascent -= additional;
}
}
}