Merge "Add LocaleList support to Paint and TextView."
diff --git a/api/current.txt b/api/current.txt
index b296672..b60bf1f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11588,6 +11588,7 @@
method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
method public void getTextBounds(char[], int, int, android.graphics.Rect);
method public java.util.Locale getTextLocale();
+ method public android.util.LocaleList getTextLocales();
method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
method public float getTextScaleX();
@@ -11643,6 +11644,7 @@
method public void setSubpixelText(boolean);
method public void setTextAlign(android.graphics.Paint.Align);
method public void setTextLocale(java.util.Locale);
+ method public void setTextLocales(android.util.LocaleList);
method public void setTextScaleX(float);
method public void setTextSize(float);
method public void setTextSkewX(float);
@@ -34207,6 +34209,7 @@
ctor public LocaleList(java.util.Locale[]);
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getPrimary();
method public boolean isEmpty();
@@ -41719,6 +41722,7 @@
method public java.lang.CharSequence getText();
method public final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
+ method public android.util.LocaleList getTextLocales();
method public float getTextScaleX();
method public float getTextSize();
method public int getTotalPaddingBottom();
@@ -41831,6 +41835,7 @@
method public final void setTextKeepState(java.lang.CharSequence);
method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
method public void setTextLocale(java.util.Locale);
+ method public void setTextLocales(android.util.LocaleList);
method public void setTextScaleX(float);
method public void setTextSize(float);
method public void setTextSize(int, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 7cc66cf..a0a5918 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11925,6 +11925,7 @@
method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
method public void getTextBounds(char[], int, int, android.graphics.Rect);
method public java.util.Locale getTextLocale();
+ method public android.util.LocaleList getTextLocales();
method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
method public float getTextScaleX();
@@ -11980,6 +11981,7 @@
method public void setSubpixelText(boolean);
method public void setTextAlign(android.graphics.Paint.Align);
method public void setTextLocale(java.util.Locale);
+ method public void setTextLocales(android.util.LocaleList);
method public void setTextScaleX(float);
method public void setTextSize(float);
method public void setTextSkewX(float);
@@ -36501,6 +36503,7 @@
ctor public LocaleList(java.util.Locale[]);
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getPrimary();
method public boolean isEmpty();
@@ -44327,6 +44330,7 @@
method public java.lang.CharSequence getText();
method public final android.content.res.ColorStateList getTextColors();
method public java.util.Locale getTextLocale();
+ method public android.util.LocaleList getTextLocales();
method public float getTextScaleX();
method public float getTextSize();
method public int getTotalPaddingBottom();
@@ -44439,6 +44443,7 @@
method public final void setTextKeepState(java.lang.CharSequence);
method public final void setTextKeepState(java.lang.CharSequence, android.widget.TextView.BufferType);
method public void setTextLocale(java.util.Locale);
+ method public void setTextLocales(android.util.LocaleList);
method public void setTextScaleX(float);
method public void setTextSize(float);
method public void setTextSize(int, float);
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index afae9ac..379651e 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -16,7 +16,11 @@
package android.util;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Size;
+
+import com.android.internal.annotations.GuardedBy;
import java.util.HashSet;
import java.util.Locale;
@@ -164,4 +168,22 @@
return new LocaleList(localeArray);
}
}
+
+ private final static Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static LocaleList sDefaultLocaleList;
+
+ // TODO: fix this to return the default system locale list once we have that
+ @NonNull @Size(min=1)
+ public static LocaleList getDefault() {
+ Locale defaultLocale = Locale.getDefault();
+ synchronized (sLock) {
+ if (sDefaultLocaleList == null || sDefaultLocaleList.size() != 1
+ || !defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
+ sDefaultLocaleList = new LocaleList(defaultLocale);
+ }
+ }
+ return sDefaultLocaleList;
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7a64377..61402ab 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -21,6 +21,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Size;
import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.annotation.XmlRes;
@@ -103,6 +104,7 @@
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
import android.util.AttributeSet;
+import android.util.LocaleList;
import android.util.Log;
import android.util.TypedValue;
import android.view.AccessibilityIterators.TextSegmentIterator;
@@ -553,7 +555,7 @@
private final TextPaint mTextPaint;
private boolean mUserSetTextScaleX;
private Layout mLayout;
- private boolean mLocaleChanged = false;
+ private boolean mLocalesChanged = false;
@ViewDebug.ExportedProperty(category = "text")
private int mGravity = Gravity.TOP | Gravity.START;
@@ -2817,32 +2819,58 @@
}
/**
- * Get the default {@link Locale} of the text in this TextView.
- * @return the default {@link Locale} of the text in this TextView.
+ * Get the default primary {@link Locale} of the text in this TextView. This will always be
+ * the first member of {@link #getTextLocales()}.
+ * @return the default primary {@link Locale} of the text in this TextView.
*/
+ @NonNull
public Locale getTextLocale() {
return mTextPaint.getTextLocale();
}
/**
- * Set the default {@link Locale} of the text in this TextView to the given value. This value
- * is used to choose appropriate typefaces for ambiguous characters. Typically used for CJK
- * locales to disambiguate Hanzi/Kanji/Hanja characters.
+ * Get the default {@link LocaleList} of the text in this TextView.
+ * @return the default {@link LocaleList} of the text in this TextView.
+ */
+ @NonNull @Size(min=1)
+ public LocaleList getTextLocales() {
+ return mTextPaint.getTextLocales();
+ }
+
+ /**
+ * Set the default {@link LocaleList} of the text in this TextView to a one-member list
+ * containing just the given value.
*
* @param locale the {@link Locale} for drawing text, must not be null.
*
- * @see Paint#setTextLocale
+ * @see #setTextLocales
*/
- public void setTextLocale(Locale locale) {
- mLocaleChanged = true;
+ public void setTextLocale(@NonNull Locale locale) {
+ mLocalesChanged = true;
mTextPaint.setTextLocale(locale);
}
+ /**
+ * Set the default {@link LocaleList} of the text in this TextView to the given value.
+ *
+ * This value is used to choose appropriate typefaces for ambiguous characters (typically used
+ * for CJK locales to disambiguate Hanzi/Kanji/Hanja characters). It also affects
+ * other aspects of text display, including line breaking.
+ *
+ * @param locales the {@link LocaleList} for drawing text, must not be null or empty.
+ *
+ * @see Paint#setTextLocales
+ */
+ public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
+ mLocalesChanged = true;
+ mTextPaint.setTextLocales(locales);
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- if (!mLocaleChanged) {
- mTextPaint.setTextLocale(Locale.getDefault());
+ if (!mLocalesChanged) {
+ mTextPaint.setTextLocales(LocaleList.getDefault());
}
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index c5d68bd..ce35b87 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,10 +17,13 @@
package android.graphics;
import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Size;
import android.text.GraphicsOperations;
import android.text.SpannableString;
import android.text.SpannedString;
import android.text.TextUtils;
+import android.util.LocaleList;
import java.util.Locale;
@@ -50,7 +53,7 @@
private float mCompatScaling;
private float mInvCompatScaling;
- private Locale mLocale;
+ private LocaleList mLocales;
private String mFontFeatureSettings;
/**
@@ -434,7 +437,7 @@
// setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
// ? HINTING_OFF : HINTING_ON);
mCompatScaling = mInvCompatScaling = 1;
- setTextLocale(Locale.getDefault());
+ setTextLocales(LocaleList.getDefault());
}
/**
@@ -474,7 +477,7 @@
mInvCompatScaling = 1;
mBidiFlags = BIDI_DEFAULT_LTR;
- setTextLocale(Locale.getDefault());
+ setTextLocales(LocaleList.getDefault());
setElegantTextHeight(false);
mFontFeatureSettings = null;
}
@@ -512,7 +515,7 @@
mInvCompatScaling = paint.mInvCompatScaling;
mBidiFlags = paint.mBidiFlags;
- mLocale = paint.mLocale;
+ mLocales = paint.mLocales;
mFontFeatureSettings = paint.mFontFeatureSettings;
}
@@ -1174,47 +1177,80 @@
}
/**
- * Get the text Locale.
+ * Get the text's primary Locale. Note that this is not all of the locale-related information
+ * Paint has. Use {@link #getTextLocales()} to get the complete list.
*
- * @return the paint's Locale used for drawing text, never null.
+ * @return the paint's primary Locale used for drawing text, never null.
*/
+ @NonNull
public Locale getTextLocale() {
- return mLocale;
+ return mLocales.getPrimary();
}
/**
- * Set the text locale.
+ * Get the text locale list.
*
- * The text locale affects how the text is drawn for some languages.
+ * @return the paint's LocaleList used for drawing text, never null or empty.
+ */
+ @NonNull @Size(min=1)
+ public LocaleList getTextLocales() {
+ return mLocales;
+ }
+
+ /**
+ * Set the text locale list to a one-member list consisting of just the locale.
*
- * For example, if the locale is {@link Locale#CHINESE} or {@link Locale#CHINA},
+ * See {@link #setTextLocales(LocaleList)} for how the locale list affects
+ * the way the text is drawn for some languages.
+ *
+ * @param locale the paint's locale value for drawing text, must not be null.
+ */
+ public void setTextLocale(@NonNull Locale locale) {
+ if (locale == null) {
+ throw new IllegalArgumentException("locale cannot be null");
+ }
+ if (mLocales != null && mLocales.size() == 1 && locale.equals(mLocales.getPrimary())) {
+ return;
+ }
+ mLocales = new LocaleList(locale);
+ native_setTextLocale(mNativePaint, locale.toString());
+ }
+
+ /**
+ * Set the text locale list.
+ *
+ * The text locale list affects how the text is drawn for some languages.
+ *
+ * For example, if the locale list contains {@link Locale#CHINESE} or {@link Locale#CHINA},
* then the text renderer will prefer to draw text using a Chinese font. Likewise,
- * if the locale is {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
- * renderer will prefer to draw text using a Japanese font.
+ * if the locale list contains {@link Locale#JAPANESE} or {@link Locale#JAPAN}, then the text
+ * renderer will prefer to draw text using a Japanese font. If the locale list contains both,
+ * the order those locales appear in the list is considered for deciding the font.
*
* This distinction is important because Chinese and Japanese text both use many
* of the same Unicode code points but their appearance is subtly different for
* each language.
*
- * By default, the text locale is initialized to the system locale (as returned
- * by {@link Locale#getDefault}). This assumes that the text to be rendered will
- * most likely be in the user's preferred language.
+ * By default, the text locale list is initialized to a one-member list just containing the
+ * system locale (as returned by {@link LocaleList#getDefault()}). This assumes that the text to
+ * be rendered will most likely be in the user's preferred language.
*
- * If the actual language of the text is known, then it can be provided to the
- * text renderer using this method. The text renderer may attempt to guess the
+ * If the actual language or languages of the text is/are known, then they can be provided to
+ * the text renderer using this method. The text renderer may attempt to guess the
* language script based on the contents of the text to be drawn independent of
- * the text locale here. Specifying the text locale just helps it do a better
- * job in certain ambiguous cases
+ * the text locale here. Specifying the text locales just helps it do a better
+ * job in certain ambiguous cases.
*
- * @param locale the paint's locale value for drawing text, must not be null.
+ * @param locales the paint's locale list for drawing text, must not be null or empty.
*/
- public void setTextLocale(Locale locale) {
- if (locale == null) {
- throw new IllegalArgumentException("locale cannot be null");
+ public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
+ if (locales == null || locales.isEmpty()) {
+ throw new IllegalArgumentException("locales cannot be null or empty");
}
- if (locale.equals(mLocale)) return;
- mLocale = locale;
- native_setTextLocale(mNativePaint, locale.toString());
+ if (locales.equals(mLocales)) return;
+ mLocales = locales;
+ // TODO: Pass the whole LocaleList to native code
+ native_setTextLocale(mNativePaint, locales.getPrimary().toString());
}
/**