mirror of
https://github.com/status-im/react-native.git
synced 2025-01-16 20:44:10 +00:00
Cache CustomStyleSpan in RCTVirtualText
Summary: @public `RCTVirtualText` is creating a new `CustomStyleSpan` on every `applySpans()` call, which is not very efficient. We can cache and reuse unchanged `CustomStyleSpans` for efficiency. This patch is doing just that. Reviewed By: sriramramani Differential Revision: D2564366
This commit is contained in:
parent
007318eb52
commit
fbe1b61fe1
@ -17,16 +17,22 @@ import android.text.style.MetricAffectingSpan;
|
|||||||
|
|
||||||
/* package */ final class FontStylingSpan extends MetricAffectingSpan {
|
/* package */ final class FontStylingSpan extends MetricAffectingSpan {
|
||||||
// text property
|
// text property
|
||||||
private final double mTextColor;
|
private double mTextColor = Double.NaN;
|
||||||
private final int mBackgroundColor;
|
private int mBackgroundColor;
|
||||||
|
|
||||||
// font properties
|
// font properties
|
||||||
private final int mFontSize;
|
private int mFontSize = -1;
|
||||||
private final int mFontStyle;
|
private int mFontStyle = -1;
|
||||||
private final int mFontWeight;
|
private int mFontWeight = -1;
|
||||||
private final @Nullable String mFontFamily;
|
private @Nullable String mFontFamily;
|
||||||
|
|
||||||
FontStylingSpan(
|
// whether or not mutation is allowed.
|
||||||
|
private boolean mFrozen = false;
|
||||||
|
|
||||||
|
FontStylingSpan() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private FontStylingSpan(
|
||||||
double textColor,
|
double textColor,
|
||||||
int backgroundColor,
|
int backgroundColor,
|
||||||
int fontSize,
|
int fontSize,
|
||||||
@ -41,6 +47,72 @@ import android.text.style.MetricAffectingSpan;
|
|||||||
mFontFamily = fontFamily;
|
mFontFamily = fontFamily;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* package */ FontStylingSpan mutableCopy() {
|
||||||
|
return new FontStylingSpan(
|
||||||
|
mTextColor,
|
||||||
|
mBackgroundColor,
|
||||||
|
mFontSize,
|
||||||
|
mFontStyle,
|
||||||
|
mFontWeight,
|
||||||
|
mFontFamily);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ boolean isFrozen() {
|
||||||
|
return mFrozen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void freeze() {
|
||||||
|
mFrozen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ double getTextColor() {
|
||||||
|
return mTextColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setTextColor(double textColor) {
|
||||||
|
mTextColor = textColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getBackgroundColor() {
|
||||||
|
return mBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setBackgroundColor(int backgroundColor) {
|
||||||
|
mBackgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getFontSize() {
|
||||||
|
return mFontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setFontSize(int fontSize) {
|
||||||
|
mFontSize = fontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getFontStyle() {
|
||||||
|
return mFontStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setFontStyle(int fontStyle) {
|
||||||
|
mFontStyle = fontStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getFontWeight() {
|
||||||
|
return mFontWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setFontWeight(int fontWeight) {
|
||||||
|
mFontWeight = fontWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ @Nullable String getFontFamily() {
|
||||||
|
return mFontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void setFontFamily(@Nullable String fontFamily) {
|
||||||
|
mFontFamily = fontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateDrawState(TextPaint ds) {
|
public void updateDrawState(TextPaint ds) {
|
||||||
if (!Double.isNaN(mTextColor)) {
|
if (!Double.isNaN(mTextColor)) {
|
||||||
|
@ -14,6 +14,7 @@ import javax.annotation.Nullable;
|
|||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.facebook.react.uimanager.PixelUtil;
|
import com.facebook.react.uimanager.PixelUtil;
|
||||||
import com.facebook.react.uimanager.ReactProp;
|
import com.facebook.react.uimanager.ReactProp;
|
||||||
@ -28,19 +29,16 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
private static final String ITALIC = "italic";
|
private static final String ITALIC = "italic";
|
||||||
private static final String NORMAL = "normal";
|
private static final String NORMAL = "normal";
|
||||||
|
|
||||||
// TODO: cache CustomStyleSpan and move remove these values from here
|
private FontStylingSpan mFontStylingSpan = new FontStylingSpan();
|
||||||
// (implemented in a followup patch)
|
|
||||||
private double mTextColor = Double.NaN;
|
|
||||||
private int mBgColor;
|
|
||||||
private int mFontSize = getDefaultFontSize();
|
|
||||||
private int mFontStyle = -1; // -1, Typeface.NORMAL or Typeface.ITALIC
|
|
||||||
private int mFontWeight = -1; // -1, Typeface.NORMAL or Typeface.BOLD
|
|
||||||
private @Nullable String mFontFamily;
|
|
||||||
|
|
||||||
// these 2 are only used between collectText() and applySpans() calls.
|
// these 2 are only used between collectText() and applySpans() calls.
|
||||||
private int mTextBegin;
|
private int mTextBegin;
|
||||||
private int mTextEnd;
|
private int mTextEnd;
|
||||||
|
|
||||||
|
RCTVirtualText() {
|
||||||
|
mFontStylingSpan.setFontSize(getDefaultFontSize());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void collectText(SpannableStringBuilder builder) {
|
protected void collectText(SpannableStringBuilder builder) {
|
||||||
int childCount = getChildCount();
|
int childCount = getChildCount();
|
||||||
@ -59,9 +57,10 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mFontStylingSpan.freeze();
|
||||||
|
|
||||||
builder.setSpan(
|
builder.setSpan(
|
||||||
// Future patch: cache last custom style span with a frozen flag
|
mFontStylingSpan,
|
||||||
new FontStylingSpan(mTextColor, mBgColor, mFontSize, mFontStyle, mFontWeight, mFontFamily),
|
|
||||||
mTextBegin,
|
mTextBegin,
|
||||||
mTextEnd,
|
mTextEnd,
|
||||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||||
@ -83,32 +82,34 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
fontSize = fontSizeFromSp(fontSizeSp);
|
fontSize = fontSizeFromSp(fontSizeSp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFontSize != fontSize) {
|
if (mFontStylingSpan.getFontSize() != fontSize) {
|
||||||
mFontSize = fontSize;
|
getSpan().setFontSize(fontSize);
|
||||||
notifyChanged(true);
|
notifyChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = ViewProps.COLOR, defaultDouble = Double.NaN)
|
@ReactProp(name = ViewProps.COLOR, defaultDouble = Double.NaN)
|
||||||
public void setColor(double textColor) {
|
public void setColor(double textColor) {
|
||||||
if (mTextColor != textColor) {
|
if (mFontStylingSpan.getTextColor() != textColor) {
|
||||||
mTextColor = textColor;
|
getSpan().setTextColor(textColor);
|
||||||
notifyChanged(false);
|
notifyChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = ViewProps.BACKGROUND_COLOR)
|
@ReactProp(name = ViewProps.BACKGROUND_COLOR)
|
||||||
public void setBackgroundColor(int backgroundColor) {
|
public void setBackgroundColor(int backgroundColor) {
|
||||||
if (mBgColor != backgroundColor) {
|
if (mFontStylingSpan.getBackgroundColor() != backgroundColor) {
|
||||||
mBgColor = backgroundColor;
|
getSpan().setBackgroundColor(backgroundColor);
|
||||||
notifyChanged(false);
|
notifyChanged(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = ViewProps.FONT_FAMILY)
|
@ReactProp(name = ViewProps.FONT_FAMILY)
|
||||||
public void setFontFamily(@Nullable String fontFamily) {
|
public void setFontFamily(@Nullable String fontFamily) {
|
||||||
mFontFamily = fontFamily;
|
if (!TextUtils.equals(mFontStylingSpan.getFontFamily(), fontFamily)) {
|
||||||
notifyChanged(true);
|
getSpan().setFontFamily(fontFamily);
|
||||||
|
notifyChanged(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = ViewProps.FONT_WEIGHT)
|
@ReactProp(name = ViewProps.FONT_WEIGHT)
|
||||||
@ -128,8 +129,8 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
fontWeight = fontWeightNumeric >= 500 ? Typeface.BOLD : Typeface.NORMAL;
|
fontWeight = fontWeightNumeric >= 500 ? Typeface.BOLD : Typeface.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFontWeight != fontWeight) {
|
if (mFontStylingSpan.getFontWeight() != fontWeight) {
|
||||||
mFontWeight = fontWeight;
|
getSpan().setFontWeight(fontWeight);
|
||||||
notifyChanged(true);
|
notifyChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,8 +148,8 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
throw new RuntimeException("invalid font style " + fontStyleString);
|
throw new RuntimeException("invalid font style " + fontStyleString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFontStyle != fontStyle) {
|
if (mFontStylingSpan.getFontStyle() != fontStyle) {
|
||||||
mFontStyle = fontStyle;
|
getSpan().setFontStyle(fontStyle);
|
||||||
notifyChanged(true);
|
notifyChanged(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,6 +162,13 @@ import com.facebook.react.uimanager.ViewProps;
|
|||||||
return (int) Math.ceil(PixelUtil.toPixelFromSP(sp));
|
return (int) Math.ceil(PixelUtil.toPixelFromSP(sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FontStylingSpan getSpan() {
|
||||||
|
if (mFontStylingSpan.isFrozen()) {
|
||||||
|
mFontStylingSpan = mFontStylingSpan.mutableCopy();
|
||||||
|
}
|
||||||
|
return mFontStylingSpan;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
|
* Return -1 if the input string is not a valid numeric fontWeight (100, 200, ..., 900), otherwise
|
||||||
* return the weight.
|
* return the weight.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user