package androidx.core.text; import android.annotation.SuppressLint; import android.os.Build; import android.text.Layout; import android.text.PrecomputedText; import android.text.Spannable; import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextDirectionHeuristic; import android.text.TextDirectionHeuristics; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.MetricAffectingSpan; import androidx.annotation.GuardedBy; import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.RestrictTo; import androidx.annotation.UiThread; import androidx.core.os.TraceCompat; import androidx.core.util.ObjectsCompat; import androidx.core.util.Preconditions; import c.d.b.a.a; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; public class PrecomputedTextCompat implements Spannable { private static final char LINE_FEED = '\n'; @NonNull @GuardedBy("sLock") private static Executor sExecutor; private static final Object sLock = new Object(); @NonNull private final int[] mParagraphEnds; @NonNull private final Params mParams; @NonNull private final Spannable mText; @Nullable private final PrecomputedText mWrapped; public static final class Params { private final int mBreakStrategy; private final int mHyphenationFrequency; @NonNull private final TextPaint mPaint; @Nullable private final TextDirectionHeuristic mTextDir; public final PrecomputedText.Params mWrapped; public static class Builder { private int mBreakStrategy; private int mHyphenationFrequency; @NonNull private final TextPaint mPaint; private TextDirectionHeuristic mTextDir; public Builder(@NonNull TextPaint textPaint) { this.mPaint = textPaint; if (Build.VERSION.SDK_INT >= 23) { this.mBreakStrategy = 1; this.mHyphenationFrequency = 1; } else { this.mHyphenationFrequency = 0; this.mBreakStrategy = 0; } this.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR; } @NonNull public Params build() { return new Params(this.mPaint, this.mTextDir, this.mBreakStrategy, this.mHyphenationFrequency); } @RequiresApi(23) public Builder setBreakStrategy(int i) { this.mBreakStrategy = i; return this; } @RequiresApi(23) public Builder setHyphenationFrequency(int i) { this.mHyphenationFrequency = i; return this; } @RequiresApi(18) public Builder setTextDirection(@NonNull TextDirectionHeuristic textDirectionHeuristic) { this.mTextDir = textDirectionHeuristic; return this; } } @RequiresApi(28) public Params(@NonNull PrecomputedText.Params params) { this.mPaint = params.getTextPaint(); this.mTextDir = params.getTextDirection(); this.mBreakStrategy = params.getBreakStrategy(); this.mHyphenationFrequency = params.getHyphenationFrequency(); this.mWrapped = Build.VERSION.SDK_INT < 29 ? null : params; } @SuppressLint({"NewApi"}) public Params(@NonNull TextPaint textPaint, @NonNull TextDirectionHeuristic textDirectionHeuristic, int i, int i2) { if (Build.VERSION.SDK_INT >= 29) { this.mWrapped = new PrecomputedText.Params.Builder(textPaint).setBreakStrategy(i).setHyphenationFrequency(i2).setTextDirection(textDirectionHeuristic).build(); } else { this.mWrapped = null; } this.mPaint = textPaint; this.mTextDir = textDirectionHeuristic; this.mBreakStrategy = i; this.mHyphenationFrequency = i2; } public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } if (!(obj instanceof Params)) { return false; } Params params = (Params) obj; return equalsWithoutTextDirection(params) && this.mTextDir == params.getTextDirection(); } @RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX}) public boolean equalsWithoutTextDirection(@NonNull Params params) { int i = Build.VERSION.SDK_INT; if ((i >= 23 && (this.mBreakStrategy != params.getBreakStrategy() || this.mHyphenationFrequency != params.getHyphenationFrequency())) || this.mPaint.getTextSize() != params.getTextPaint().getTextSize() || this.mPaint.getTextScaleX() != params.getTextPaint().getTextScaleX() || this.mPaint.getTextSkewX() != params.getTextPaint().getTextSkewX() || this.mPaint.getLetterSpacing() != params.getTextPaint().getLetterSpacing() || !TextUtils.equals(this.mPaint.getFontFeatureSettings(), params.getTextPaint().getFontFeatureSettings()) || this.mPaint.getFlags() != params.getTextPaint().getFlags()) { return false; } if (i >= 24) { if (!this.mPaint.getTextLocales().equals(params.getTextPaint().getTextLocales())) { return false; } } else if (!this.mPaint.getTextLocale().equals(params.getTextPaint().getTextLocale())) { return false; } return this.mPaint.getTypeface() == null ? params.getTextPaint().getTypeface() == null : this.mPaint.getTypeface().equals(params.getTextPaint().getTypeface()); } @RequiresApi(23) public int getBreakStrategy() { return this.mBreakStrategy; } @RequiresApi(23) public int getHyphenationFrequency() { return this.mHyphenationFrequency; } @Nullable @RequiresApi(18) public TextDirectionHeuristic getTextDirection() { return this.mTextDir; } @NonNull public TextPaint getTextPaint() { return this.mPaint; } public int hashCode() { return Build.VERSION.SDK_INT >= 24 ? ObjectsCompat.hash(Float.valueOf(this.mPaint.getTextSize()), Float.valueOf(this.mPaint.getTextScaleX()), Float.valueOf(this.mPaint.getTextSkewX()), Float.valueOf(this.mPaint.getLetterSpacing()), Integer.valueOf(this.mPaint.getFlags()), this.mPaint.getTextLocales(), this.mPaint.getTypeface(), Boolean.valueOf(this.mPaint.isElegantTextHeight()), this.mTextDir, Integer.valueOf(this.mBreakStrategy), Integer.valueOf(this.mHyphenationFrequency)) : ObjectsCompat.hash(Float.valueOf(this.mPaint.getTextSize()), Float.valueOf(this.mPaint.getTextScaleX()), Float.valueOf(this.mPaint.getTextSkewX()), Float.valueOf(this.mPaint.getLetterSpacing()), Integer.valueOf(this.mPaint.getFlags()), this.mPaint.getTextLocale(), this.mPaint.getTypeface(), Boolean.valueOf(this.mPaint.isElegantTextHeight()), this.mTextDir, Integer.valueOf(this.mBreakStrategy), Integer.valueOf(this.mHyphenationFrequency)); } public String toString() { StringBuilder sb = new StringBuilder("{"); StringBuilder L = a.L("textSize="); L.append(this.mPaint.getTextSize()); sb.append(L.toString()); sb.append(", textScaleX=" + this.mPaint.getTextScaleX()); sb.append(", textSkewX=" + this.mPaint.getTextSkewX()); int i = Build.VERSION.SDK_INT; StringBuilder L2 = a.L(", letterSpacing="); L2.append(this.mPaint.getLetterSpacing()); sb.append(L2.toString()); sb.append(", elegantTextHeight=" + this.mPaint.isElegantTextHeight()); if (i >= 24) { StringBuilder L3 = a.L(", textLocale="); L3.append(this.mPaint.getTextLocales()); sb.append(L3.toString()); } else { StringBuilder L4 = a.L(", textLocale="); L4.append(this.mPaint.getTextLocale()); sb.append(L4.toString()); } StringBuilder L5 = a.L(", typeface="); L5.append(this.mPaint.getTypeface()); sb.append(L5.toString()); if (i >= 26) { StringBuilder L6 = a.L(", variationSettings="); L6.append(this.mPaint.getFontVariationSettings()); sb.append(L6.toString()); } StringBuilder L7 = a.L(", textDir="); L7.append(this.mTextDir); sb.append(L7.toString()); sb.append(", breakStrategy=" + this.mBreakStrategy); sb.append(", hyphenationFrequency=" + this.mHyphenationFrequency); sb.append("}"); return sb.toString(); } } public static class PrecomputedTextFutureTask extends FutureTask { public static class PrecomputedTextCallback implements Callable { private Params mParams; private CharSequence mText; public PrecomputedTextCallback(@NonNull Params params, @NonNull CharSequence charSequence) { this.mParams = params; this.mText = charSequence; } @Override // java.util.concurrent.Callable public PrecomputedTextCompat call() throws Exception { return PrecomputedTextCompat.create(this.mText, this.mParams); } } public PrecomputedTextFutureTask(@NonNull Params params, @NonNull CharSequence charSequence) { super(new PrecomputedTextCallback(params, charSequence)); } } @RequiresApi(28) private PrecomputedTextCompat(@NonNull PrecomputedText precomputedText, @NonNull Params params) { this.mText = precomputedText; this.mParams = params; this.mParagraphEnds = null; this.mWrapped = Build.VERSION.SDK_INT < 29 ? null : precomputedText; } private PrecomputedTextCompat(@NonNull CharSequence charSequence, @NonNull Params params, @NonNull int[] iArr) { this.mText = new SpannableString(charSequence); this.mParams = params; this.mParagraphEnds = iArr; this.mWrapped = null; } @SuppressLint({"NewApi"}) public static PrecomputedTextCompat create(@NonNull CharSequence charSequence, @NonNull Params params) { PrecomputedText.Params params2; Preconditions.checkNotNull(charSequence); Preconditions.checkNotNull(params); try { TraceCompat.beginSection("PrecomputedText"); if (Build.VERSION.SDK_INT >= 29 && (params2 = params.mWrapped) != null) { return new PrecomputedTextCompat(PrecomputedText.create(charSequence, params2), params); } ArrayList arrayList = new ArrayList(); int length = charSequence.length(); int i = 0; while (i < length) { int indexOf = TextUtils.indexOf(charSequence, (char) LINE_FEED, i, length); i = indexOf < 0 ? length : indexOf + 1; arrayList.add(Integer.valueOf(i)); } int[] iArr = new int[arrayList.size()]; for (int i2 = 0; i2 < arrayList.size(); i2++) { iArr[i2] = ((Integer) arrayList.get(i2)).intValue(); } if (Build.VERSION.SDK_INT >= 23) { StaticLayout.Builder.obtain(charSequence, 0, charSequence.length(), params.getTextPaint(), Integer.MAX_VALUE).setBreakStrategy(params.getBreakStrategy()).setHyphenationFrequency(params.getHyphenationFrequency()).setTextDirection(params.getTextDirection()).build(); } else { new StaticLayout(charSequence, params.getTextPaint(), Integer.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } PrecomputedTextCompat precomputedTextCompat = new PrecomputedTextCompat(charSequence, params, iArr); TraceCompat.endSection(); return precomputedTextCompat; } finally { TraceCompat.endSection(); } } @UiThread public static Future getTextFuture(@NonNull CharSequence charSequence, @NonNull Params params, @Nullable Executor executor) { PrecomputedTextFutureTask precomputedTextFutureTask = new PrecomputedTextFutureTask(params, charSequence); if (executor == null) { synchronized (sLock) { if (sExecutor == null) { sExecutor = Executors.newFixedThreadPool(1); } executor = sExecutor; } } executor.execute(precomputedTextFutureTask); return precomputedTextFutureTask; } @Override // java.lang.CharSequence public char charAt(int i) { return this.mText.charAt(i); } @IntRange(from = 0) @SuppressLint({"NewApi"}) public int getParagraphCount() { return Build.VERSION.SDK_INT >= 29 ? this.mWrapped.getParagraphCount() : this.mParagraphEnds.length; } @IntRange(from = 0) @SuppressLint({"NewApi"}) public int getParagraphEnd(@IntRange(from = 0) int i) { Preconditions.checkArgumentInRange(i, 0, getParagraphCount(), "paraIndex"); return Build.VERSION.SDK_INT >= 29 ? this.mWrapped.getParagraphEnd(i) : this.mParagraphEnds[i]; } @IntRange(from = 0) @SuppressLint({"NewApi"}) public int getParagraphStart(@IntRange(from = 0) int i) { Preconditions.checkArgumentInRange(i, 0, getParagraphCount(), "paraIndex"); if (Build.VERSION.SDK_INT >= 29) { return this.mWrapped.getParagraphStart(i); } if (i == 0) { return 0; } return this.mParagraphEnds[i - 1]; } @NonNull public Params getParams() { return this.mParams; } @Nullable @RequiresApi(28) @RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX}) public PrecomputedText getPrecomputedText() { Spannable spannable = this.mText; if (spannable instanceof PrecomputedText) { return (PrecomputedText) spannable; } return null; } @Override // android.text.Spanned public int getSpanEnd(Object obj) { return this.mText.getSpanEnd(obj); } @Override // android.text.Spanned public int getSpanFlags(Object obj) { return this.mText.getSpanFlags(obj); } @Override // android.text.Spanned public int getSpanStart(Object obj) { return this.mText.getSpanStart(obj); } @Override // android.text.Spanned @SuppressLint({"NewApi"}) public T[] getSpans(int i, int i2, Class cls) { return Build.VERSION.SDK_INT >= 29 ? (T[]) this.mWrapped.getSpans(i, i2, cls) : (T[]) this.mText.getSpans(i, i2, cls); } @Override // java.lang.CharSequence public int length() { return this.mText.length(); } @Override // android.text.Spanned public int nextSpanTransition(int i, int i2, Class cls) { return this.mText.nextSpanTransition(i, i2, cls); } @Override // android.text.Spannable @SuppressLint({"NewApi"}) public void removeSpan(Object obj) { if (obj instanceof MetricAffectingSpan) { throw new IllegalArgumentException("MetricAffectingSpan can not be removed from PrecomputedText."); } else if (Build.VERSION.SDK_INT >= 29) { this.mWrapped.removeSpan(obj); } else { this.mText.removeSpan(obj); } } @Override // android.text.Spannable @SuppressLint({"NewApi"}) public void setSpan(Object obj, int i, int i2, int i3) { if (obj instanceof MetricAffectingSpan) { throw new IllegalArgumentException("MetricAffectingSpan can not be set to PrecomputedText."); } else if (Build.VERSION.SDK_INT >= 29) { this.mWrapped.setSpan(obj, i, i2, i3); } else { this.mText.setSpan(obj, i, i2, i3); } } @Override // java.lang.CharSequence public CharSequence subSequence(int i, int i2) { return this.mText.subSequence(i, i2); } @Override // java.lang.CharSequence, java.lang.Object @NonNull public String toString() { return this.mText.toString(); } }