Skip to content

Commit

Permalink
Minimize EditText Spans 8/9: CustomStyleSpan (#36577)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #36577

This is part of a series of changes to minimize the number of spans committed to EditText, as a mitigation for platform issues on Samsung devices. See this [GitHub thread]( #35936 (comment)) for greater context on the platform behavior.

This change allows us to strip CustomStyleSpan. We already set all but `fontVariant` on the underlying EditText, so we just need to route that through as well.

Note that because this span is non-parcelable, it is seemingly not subject to the buggy behavior on Samsung devices of infinitely cloning the spans, but non-parcelable spans have different issues on the devices (they disappear), so moving `fontVariant` to the top-level makes sense here.

Changelog:
[Android][Fixed] - Minimize EditText Spans 8/N: CustomStyleSpan

Reviewed By: javache

Differential Revision: D44297384

fbshipit-source-id: ed4c000e961dd456a2a8f4397e27c23a87defb6e
  • Loading branch information
NickGerleman authored and kelset committed Apr 25, 2023
1 parent 3b07e7e commit e89f919
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ public int getWeight() {
return mFontFamily;
}

public @Nullable String getFontFeatureSettings() {
return mFeatureSettings;
}

private static void apply(
Paint paint,
int style,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import com.facebook.react.views.view.ReactViewBackgroundManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* A wrapper around the EditText that lets us better control what happens when an EditText gets
Expand Down Expand Up @@ -482,6 +483,14 @@ public void setFontStyle(String fontStyleString) {
}
}

@Override
public void setFontFeatureSettings(String fontFeatureSettings) {
if (!Objects.equals(fontFeatureSettings, getFontFeatureSettings())) {
super.setFontFeatureSettings(fontFeatureSettings);
mTypefaceDirty = true;
}
}

public void maybeUpdateTypeface() {
if (!mTypefaceDirty) {
return;
Expand All @@ -493,6 +502,17 @@ public void maybeUpdateTypeface() {
ReactTypefaceUtils.applyStyles(
getTypeface(), mFontStyle, mFontWeight, mFontFamily, getContext().getAssets());
setTypeface(newTypeface);

// Match behavior of CustomStyleSpan and enable SUBPIXEL_TEXT_FLAG when setting anything
// nonstandard
if (mFontStyle != UNSET
|| mFontWeight != UNSET
|| mFontFamily != null
|| getFontFeatureSettings() != null) {
setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
} else {
setPaintFlags(getPaintFlags() & (~Paint.SUBPIXEL_TEXT_FLAG));
}
}

// VisibleForTesting from {@link TextInputEventsTestCase}.
Expand Down Expand Up @@ -702,6 +722,19 @@ public boolean test(CustomLetterSpacingSpan span) {
}
});
}

stripSpansOfKind(
sb,
CustomStyleSpan.class,
new SpanPredicate<CustomStyleSpan>() {
@Override
public boolean test(CustomStyleSpan span) {
return span.getStyle() == mFontStyle
&& Objects.equals(span.getFontFamily(), mFontFamily)
&& span.getWeight() == mFontWeight
&& Objects.equals(span.getFontFeatureSettings(), getFontFeatureSettings());
}
});
}

private <T> void stripSpansOfKind(
Expand Down Expand Up @@ -759,6 +792,22 @@ private void restoreStyleEquivalentSpans(SpannableStringBuilder workingText) {
spanFlags);
}
}

if (mFontStyle != UNSET
|| mFontWeight != UNSET
|| mFontFamily != null
|| getFontFeatureSettings() != null) {
workingText.setSpan(
new CustomStyleSpan(
mFontStyle,
mFontWeight,
getFontFeatureSettings(),
mFontFamily,
getContext().getAssets()),
0,
workingText.length(),
spanFlags);
}
}

private static boolean sameTextForSpan(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import com.facebook.react.views.text.ReactBaseTextShadowNode;
import com.facebook.react.views.text.ReactTextUpdate;
import com.facebook.react.views.text.ReactTextViewManagerCallback;
import com.facebook.react.views.text.ReactTypefaceUtils;
import com.facebook.react.views.text.TextAttributeProps;
import com.facebook.react.views.text.TextInlineImageSpan;
import com.facebook.react.views.text.TextLayoutManager;
Expand Down Expand Up @@ -397,6 +398,11 @@ public void setFontStyle(ReactEditText view, @Nullable String fontStyle) {
view.setFontStyle(fontStyle);
}

@ReactProp(name = ViewProps.FONT_VARIANT)
public void setFontVariant(ReactEditText view, @Nullable ReadableArray fontVariant) {
view.setFontFeatureSettings(ReactTypefaceUtils.parseFontVariant(fontVariant));
}

@ReactProp(name = ViewProps.INCLUDE_FONT_PADDING, defaultBoolean = true)
public void setIncludeFontPadding(ReactEditText view, boolean includepad) {
view.setIncludeFontPadding(includepad);
Expand Down

0 comments on commit e89f919

Please sign in to comment.