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

Commit c38b5195 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Replace Locale with LocaleList in LocaleSpan.

This is a straightforward upgrading of LocaleSpan.

LocaleSpan was designed to be a mechanism to override text locale only
in a certain substring.  Since now text locale supports multiple locales
with LocaleList, it should make sense to let LocaleSpan have the ability
to have multiple locales with LocaleList.

This CL also addresses an existing issue that LocaleSpan maintained only
Language/Country/Variant tags.  Now Locale data associated with a
LocaleSpan is guaranteed to be preserved as long as each of them can be
created from a BCP 47 language tag with Locale#forLanguageTag(String).

Bug: 26567158
Change-Id: Ib754796d399cd00f9d02005df88874a5cd5c7642
parent cbc5bd57
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -38121,9 +38121,11 @@ package android.text.style {
  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
    ctor public LocaleSpan(java.util.Locale);
    ctor public LocaleSpan(android.util.LocaleList);
    ctor public LocaleSpan(android.os.Parcel);
    method public int describeContents();
    method public java.util.Locale getLocale();
    method public android.util.LocaleList getLocales();
    method public int getSpanTypeId();
    method public void updateDrawState(android.text.TextPaint);
    method public void updateMeasureState(android.text.TextPaint);
+2 −0
Original line number Diff line number Diff line
@@ -40480,9 +40480,11 @@ package android.text.style {
  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
    ctor public LocaleSpan(java.util.Locale);
    ctor public LocaleSpan(android.util.LocaleList);
    ctor public LocaleSpan(android.os.Parcel);
    method public int describeContents();
    method public java.util.Locale getLocale();
    method public android.util.LocaleList getLocales();
    method public int getSpanTypeId();
    method public void updateDrawState(android.text.TextPaint);
    method public void updateMeasureState(android.text.TextPaint);
+2 −0
Original line number Diff line number Diff line
@@ -38137,9 +38137,11 @@ package android.text.style {
  public class LocaleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
    ctor public LocaleSpan(java.util.Locale);
    ctor public LocaleSpan(android.util.LocaleList);
    ctor public LocaleSpan(android.os.Parcel);
    method public int describeContents();
    method public java.util.Locale getLocale();
    method public android.util.LocaleList getLocales();
    method public int getSpanTypeId();
    method public void updateDrawState(android.text.TextPaint);
    method public void updateMeasureState(android.text.TextPaint);
+53 −18
Original line number Diff line number Diff line
@@ -16,30 +16,56 @@

package android.text.style;

import com.android.internal.util.Preconditions;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Paint;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.LocaleList;

import java.util.Locale;

/**
 * Changes the {@link Locale} of the text to which the span is attached.
 */
public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {
    private final Locale mLocale;
    @NonNull
    private final LocaleList mLocales;

    /**
     * Creates a {@link LocaleSpan} from a well-formed {@link Locale}.  Note that only
     * {@link Locale} objects that can be created by {@link Locale#forLanguageTag(String)} are
     * supported.
     *
     * <p><b>Caveat:</b> Do not specify any {@link Locale} object that cannot be created by
     * {@link Locale#forLanguageTag(String)}.  {@code new Locale(" a ", " b c", " d")} is an
     * example of such a malformed {@link Locale} object.</p>
     *
     * @param locale The {@link Locale} of the text to which the span is attached.
     *
     * @see #LocaleSpan(LocaleList)
     */
    public LocaleSpan(@Nullable Locale locale) {
        mLocales = new LocaleList(locale);
    }

    /**
     * Creates a LocaleSpan.
     * @param locale The {@link Locale} of the text to which the span is
     * attached.
     * Creates a {@link LocaleSpan} from {@link LocaleList}.
     *
     * @param locales The {@link LocaleList} of the text to which the span is attached.
     * @throws NullPointerException if {@code locales} is null
     */
    public LocaleSpan(Locale locale) {
        mLocale = locale;
    public LocaleSpan(@NonNull LocaleList locales) {
        Preconditions.checkNotNull(locales, "locales cannot be null");
        mLocales = locales;
    }

    public LocaleSpan(Parcel src) {
        mLocale = new Locale(src.readString(), src.readString(), src.readString());
    public LocaleSpan(Parcel source) {
        mLocales = LocaleList.CREATOR.createFromParcel(source);
    }

    @Override
@@ -64,31 +90,40 @@ public class LocaleSpan extends MetricAffectingSpan implements ParcelableSpan {

    /** @hide */
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mLocale.getLanguage());
        dest.writeString(mLocale.getCountry());
        dest.writeString(mLocale.getVariant());
        mLocales.writeToParcel(dest, flags);
    }

    /**
     * Returns the {@link Locale}.
     * @return The {@link Locale} for this span.  If multiple locales are associated with this
     * span, only the first locale is returned.  {@code null} if no {@link Locale} is specified.
     *
     * @return The {@link Locale} for this span.
     * @see LocaleList#getPrimary()
     * @see #getLocales()
     */
    @Nullable
    public Locale getLocale() {
        return mLocale;
        return mLocales.getPrimary();
    }

    /**
     * @return The entire list of locales that are associated with this span.
     */
    @NonNull
    public LocaleList getLocales() {
        return mLocales;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mLocale);
        apply(ds, mLocales);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mLocale);
        apply(paint, mLocales);
    }

    private static void apply(Paint paint, Locale locale) {
        paint.setTextLocale(locale);
    private static void apply(@NonNull Paint paint, @NonNull LocaleList locales) {
        paint.setTextLocales(locales);
    }
}