Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e84e04b4 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Make LineBreakConfig and its span parcelable

To be able to use it in remote views, make LineBreakConfigSpan
ParcelableSpan.
Also, to be able to LineBreakConfigSpan parcelable, it need to be
final class. Due to this change, NoBreakSpan and NoHyphantionSpan is
no longer possible. So, changed them to a create methods.

Bug: 307666854
Test: atest CtsTextTestCases
Change-Id: Ifbf5a264d61c47a79ccb48a673f853f355e17c61
parent b7a1e303
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -17708,11 +17708,14 @@ package android.graphics.pdf {
package android.graphics.text {
  public final class LineBreakConfig {
  public final class LineBreakConfig implements android.os.Parcelable {
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public int describeContents();
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public int getHyphenation();
    method public int getLineBreakStyle();
    method public int getLineBreakWordStyle();
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public android.graphics.text.LineBreakConfig merge(@NonNull android.graphics.text.LineBreakConfig);
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public void writeToParcel(@NonNull android.os.Parcel, int);
    field @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public static final android.os.Parcelable.Creator<android.graphics.text.LineBreakConfig> CREATOR;
    field @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public static final int HYPHENATION_DISABLED = 0; // 0x0
    field @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public static final int HYPHENATION_ENABLED = 1; // 0x1
    field @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public static final int HYPHENATION_UNSPECIFIED = -1; // 0xffffffff
@@ -48011,17 +48014,15 @@ package android.text.style {
    method public void writeToParcel(@NonNull android.os.Parcel, int);
  }
  @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public class LineBreakConfigSpan {
  @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public final class LineBreakConfigSpan implements android.text.ParcelableSpan {
    ctor @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public LineBreakConfigSpan(@NonNull android.graphics.text.LineBreakConfig);
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public static android.text.style.LineBreakConfigSpan createNoBreakSpan();
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public static android.text.style.LineBreakConfigSpan createNoHyphenationSpan();
    method public int describeContents();
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
  }
  @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public static final class LineBreakConfigSpan.NoBreakSpan extends android.text.style.LineBreakConfigSpan {
    ctor @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public LineBreakConfigSpan.NoBreakSpan();
  }
  @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public static final class LineBreakConfigSpan.NoHyphenationSpan extends android.text.style.LineBreakConfigSpan {
    ctor @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") public LineBreakConfigSpan.NoHyphenationSpan();
    method public int getSpanTypeId();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.text.style.LineBreakConfigSpan> CREATOR;
  }
  public interface LineHeightSpan extends android.text.style.ParagraphStyle android.text.style.WrapTogetherSpan {
+54 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.text.LineBreakConfig;
import android.text.Annotation;
import android.text.Spannable;
import android.text.SpannableString;
@@ -35,6 +36,7 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.LineBreakConfigSpan;
import android.text.style.LineHeightSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
@@ -176,6 +178,10 @@ public final class StringBlock implements Closeable {
                        mStyleIDs.listItemId = styleId;
                    } else if (styleTag.equals("marquee")) {
                        mStyleIDs.marqueeId = styleId;
                    } else if (styleTag.equals("nobreak")) {
                        mStyleIDs.mNoBreakId = styleId;
                    } else if (styleTag.equals("nohyphen")) {
                        mStyleIDs.mNoHyphenId = styleId;
                    }
                }

@@ -224,6 +230,8 @@ public final class StringBlock implements Closeable {
        private int strikeId = -1;
        private int listItemId = -1;
        private int marqueeId = -1;
        private int mNoBreakId = -1;
        private int mNoHyphenId = -1;
    }

    @Nullable
@@ -285,12 +293,19 @@ public final class StringBlock implements Closeable {
                buffer.setSpan(TextUtils.TruncateAt.MARQUEE,
                               style[i+1], style[i+2]+1,
                               Spannable.SPAN_INCLUSIVE_INCLUSIVE);
            } else if (type == ids.mNoBreakId) {
                buffer.setSpan(LineBreakConfigSpan.createNoBreakSpan(),
                        style[i + 1], style[i + 2] + 1,
                        Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
            } else if (type == ids.mNoHyphenId) {
                buffer.setSpan(LineBreakConfigSpan.createNoHyphenationSpan(),
                        style[i + 1], style[i + 2] + 1,
                        Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
            } else {
                String tag = nativeGetString(mNative, type);
                if (tag == null) {
                    return null;
                }

                if (tag.startsWith("font;")) {
                    String sub;

@@ -367,6 +382,44 @@ public final class StringBlock implements Closeable {
                                       style[i+1], style[i+2]+1,
                                       Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                } else if (tag.startsWith("lineBreakConfig;")) {
                    String lbStyleStr = subtag(tag, ";style=");
                    int lbStyle = LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED;
                    if (lbStyleStr != null) {
                        if (lbStyleStr.equals("none")) {
                            lbStyle = LineBreakConfig.LINE_BREAK_STYLE_NONE;
                        } else if (lbStyleStr.equals("normal")) {
                            lbStyle = LineBreakConfig.LINE_BREAK_STYLE_NORMAL;
                        } else if (lbStyleStr.equals("loose")) {
                            lbStyle = LineBreakConfig.LINE_BREAK_STYLE_LOOSE;
                        } else if (lbStyleStr.equals("strict")) {
                            lbStyle = LineBreakConfig.LINE_BREAK_STYLE_STRICT;
                        } else {
                            Log.w(TAG, "Unknown LineBreakConfig style: " + lbStyleStr);
                        }
                    }

                    String lbWordStyleStr = subtag(tag, ";wordStyle=");
                    int lbWordStyle = LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED;
                    if (lbWordStyleStr != null) {
                        if (lbWordStyleStr.equals("none")) {
                            lbWordStyle = LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE;
                        } else if (lbWordStyleStr.equals("phrase")) {
                            lbWordStyle = LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE;
                        } else {
                            Log.w(TAG, "Unknown LineBreakConfig word style: " + lbWordStyleStr);
                        }
                    }

                    // Attach span only when the both lbStyle and lbWordStyle are valid.
                    if (lbStyle != LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED
                            || lbWordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_UNSPECIFIED) {
                        buffer.setSpan(new LineBreakConfigSpan(
                                new LineBreakConfig(lbStyle, lbWordStyle,
                                        LineBreakConfig.HYPHENATION_UNSPECIFIED)),
                                style[i + 1], style[i + 2] + 1,
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                }
            }

+8 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.text.style.EasyEditSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.LineBackgroundSpan;
import android.text.style.LineBreakConfigSpan;
import android.text.style.LineHeightSpan;
import android.text.style.LocaleSpan;
import android.text.style.ParagraphStyle;
@@ -787,7 +788,9 @@ public class TextUtils {
    /** @hide */
    public static final int ACCESSIBILITY_REPLACEMENT_SPAN = 29;
    /** @hide */
    public static final int LAST_SPAN = ACCESSIBILITY_REPLACEMENT_SPAN;
    public static final int LINE_BREAK_CONFIG_SPAN = 30;
    /** @hide */
    public static final int LAST_SPAN = LINE_BREAK_CONFIG_SPAN;

    /**
     * Flatten a CharSequence and whatever styles can be copied across processes
@@ -991,6 +994,10 @@ public class TextUtils {
                    span = new AccessibilityReplacementSpan(p);
                    break;

                case LINE_BREAK_CONFIG_SPAN:
                    span = LineBreakConfigSpan.CREATOR.createFromParcel(p);
                    break;

                default:
                    throw new RuntimeException("bogus span encoding " + kind);
                }
+65 −31
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.graphics.text.LineBreakConfig;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;

import java.util.Objects;

@@ -28,7 +31,7 @@ import java.util.Objects;
 * LineBreakSpan for changing line break style of the specific region of the text.
 */
@FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
public class LineBreakConfigSpan {
public final class LineBreakConfigSpan implements ParcelableSpan {
    private final LineBreakConfig mLineBreakConfig;

    /**
@@ -49,6 +52,28 @@ public class LineBreakConfigSpan {
        return mLineBreakConfig;
    }

    /**
     * A specialized {@link LineBreakConfigSpan} that used for preventing line break.
     *
     * This is useful when you want to preserve some words in the same line.
     * Note that even if this style is specified, the grapheme based line break is still performed
     * for preventing clipping text.
     *
     * @see LineBreakConfigSpan
     */
    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static @NonNull LineBreakConfigSpan createNoBreakSpan() {
        return new LineBreakConfigSpan(sNoBreakConfig);
    }

    /**
     * A specialized {@link LineBreakConfigSpan} that used for preventing hyphenation.
     */
    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static @NonNull LineBreakConfigSpan createNoHyphenationSpan() {
        return new LineBreakConfigSpan(sNoHyphenationConfig);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
@@ -75,37 +100,46 @@ public class LineBreakConfigSpan {
            .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NO_BREAK)
            .build();

    /**
     * A specialized {@link LineBreakConfigSpan} that used for preventing hyphenation.
     */
    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static final class NoHyphenationSpan extends LineBreakConfigSpan {
        /**
         * Construct a new {@link NoHyphenationSpan}.
         */
        @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
        public NoHyphenationSpan() {
            super(sNoHyphenationConfig);
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    @Override
    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    /**
     * A specialized {@link LineBreakConfigSpan} that used for preventing line break.
     *
     * This is useful when you want to preserve some words in the same line.
     * Note that even if this style is specified, the grapheme based line break is still performed
     * for preventing clipping text.
     *
     * @see LineBreakConfigSpan
     */
    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static final class NoBreakSpan extends LineBreakConfigSpan {
        /**
         * Construct a new {@link NoBreakSpan}.
         */
        @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
        public NoBreakSpan() {
            super(sNoBreakConfig);
    /** @hide */
    @Override
    public int getSpanTypeIdInternal() {
        return TextUtils.LINE_BREAK_CONFIG_SPAN;
    }

    /** @hide */
    @Override
    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
        dest.writeParcelable(mLineBreakConfig, flags);
    }

    @NonNull
    public static final Creator<LineBreakConfigSpan> CREATOR = new Creator<>() {

        @Override
        public LineBreakConfigSpan createFromParcel(Parcel source) {
            LineBreakConfig lbc = source.readParcelable(
                    LineBreakConfig.class.getClassLoader(), LineBreakConfig.class);
            return new LineBreakConfigSpan(lbc);
        }

        @Override
        public LineBreakConfigSpan[] newArray(int size) {
            return new LineBreakConfigSpan[size];
        }
    };
}
+38 −4
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.os.Build;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -40,7 +42,7 @@ import java.util.Objects;
 * <a href="https://www.w3.org/TR/css-text-3/#line-break-property" class="external">
 * line-break property</a> for more information.
 */
public final class LineBreakConfig {
public final class LineBreakConfig implements Parcelable {

    /**
     * A feature ID for automatic line break word style.
@@ -161,12 +163,12 @@ public final class LineBreakConfig {
     *
     * This is useful when you want to preserve some words in the same line by using
     * {@link android.text.style.LineBreakConfigSpan} or
     * {@link android.text.style.LineBreakConfigSpan.NoBreakSpan} as a shorthand.
     * {@link android.text.style.LineBreakConfigSpan#createNoBreakSpan()} as a shorthand.
     * Note that even if this style is specified, the grapheme based line break is still performed
     * for preventing clipping text.
     *
     * @see android.text.style.LineBreakConfigSpan
     * @see android.text.style.LineBreakConfigSpan.NoBreakSpan
     * @see android.text.style.LineBreakConfigSpan#createNoBreakSpan()
     */
    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static final int LINE_BREAK_STYLE_NO_BREAK = 4;
@@ -457,8 +459,9 @@ public final class LineBreakConfig {
     *
     * <p>Use {@link LineBreakConfig.Builder} to create the
     * {@code LineBreakConfig} instance.
     * @hide
     */
    private LineBreakConfig(@LineBreakStyle int lineBreakStyle,
    public LineBreakConfig(@LineBreakStyle int lineBreakStyle,
            @LineBreakWordStyle int lineBreakWordStyle,
            @Hyphenation int hyphenation) {
        mLineBreakStyle = lineBreakStyle;
@@ -606,4 +609,35 @@ public final class LineBreakConfig {
                + ", mHyphenation= " + mHyphenation
                + '}';
    }

    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    @Override
    public int describeContents() {
        return 0;
    }

    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mLineBreakStyle);
        dest.writeInt(mLineBreakWordStyle);
        dest.writeInt(mHyphenation);
    }

    @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN)
    public static final @NonNull Creator<LineBreakConfig> CREATOR = new Creator<>() {

        @Override
        public LineBreakConfig createFromParcel(Parcel source) {
            final int lineBreakStyle = source.readInt();
            final int lineBreakWordStyle = source.readInt();
            final int hyphenation = source.readInt();
            return new LineBreakConfig(lineBreakStyle, lineBreakWordStyle, hyphenation);
        }

        @Override
        public LineBreakConfig[] newArray(int size) {
            return new LineBreakConfig[size];
        }
    };
}