diff options
author | Seigo Nonaka <nona@google.com> | 2017-03-28 16:16:41 -0700 |
---|---|---|
committer | Seigo Nonaka <nona@google.com> | 2017-04-03 13:55:07 -0700 |
commit | ff55115121a7a2753ba2265cb3201a3a14c0874d (patch) | |
tree | 151c60917705792e4afa5bfc5b7820228a72cc50 | |
parent | be436bdefe1947c01eb4b42bf1b864b1e86b7fb9 (diff) |
Reorganize font enumeration API.
This CL cleans up APIs around font variation settings.
- Remove FontConfig and FontManager public API.
- Remove FontManagerService from system service.
- Extract inner class FontConfig.Axis as top-level class FontVariationAxis.
This is used by Typeface.Builder public API to create new Typeface.
- Introduce and expose FontVariationAxis utility functions from/to string.
- Throws if the invalid font variation settings is passed.
Test: android.text.cts.FontVariationAxisTest passes
Test: android.graphics.cts.TypefaceTest passes
Test: android.graphics.cts.PaintTest passes
Change-Id: I9ccafe7a53935960566243e2856e166878ca59ae
26 files changed, 422 insertions, 730 deletions
diff --git a/Android.mk b/Android.mk index eb649c9152c3..8b68c5cc3ebc 100644 --- a/Android.mk +++ b/Android.mk @@ -366,7 +366,6 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ core/java/com/android/internal/backup/IBackupTransport.aidl \ core/java/com/android/internal/backup/IObbBackupService.aidl \ - core/java/com/android/internal/font/IFontManager.aidl \ core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \ core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \ core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \ diff --git a/api/current.txt b/api/current.txt index d18d88137720..d44c173c4dd2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8883,7 +8883,6 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -13232,7 +13231,7 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -13766,8 +13765,8 @@ package android.graphics { method public static android.graphics.Typeface.Builder obtain(); method public void recycle(); method public void reset(); - method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String); - method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]); + method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); method public android.graphics.Typeface.Builder setItalic(int); method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String); method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File); @@ -14377,6 +14376,21 @@ package android.graphics.fonts { field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR; } + public final class FontVariationAxis implements android.os.Parcelable { + ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public int describeContents(); + method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public float getStyleValue(); + method public java.lang.String getTag(); + method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR; + } + + public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception { + ctor public FontVariationAxis.InvalidFormatException(java.lang.String); + } + } package android.graphics.pdf { @@ -41037,65 +41051,6 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } - public final class FontConfig implements android.os.Parcelable { - ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]); - method public int describeContents(); - method public android.text.FontConfig.Alias[] getAliases(); - method public android.text.FontConfig.Family[] getFamilies(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; - } - - public static final class FontConfig.Alias implements android.os.Parcelable { - ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); - method public int describeContents(); - method public java.lang.String getName(); - method public java.lang.String getToName(); - method public int getWeight(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; - } - - public static final class FontConfig.Axis implements android.os.Parcelable { - ctor public FontConfig.Axis(int, float); - ctor public FontConfig.Axis(java.lang.String, float); - method public int describeContents(); - method public float getStyleValue(); - method public int getTag(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; - } - - public static final class FontConfig.Family implements android.os.Parcelable { - ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int); - method public int describeContents(); - method public android.text.FontConfig.Font[] getFonts(); - method public java.lang.String getLanguage(); - method public java.lang.String getName(); - method public int getVariant(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; - field public static final int VARIANT_COMPACT = 1; // 0x1 - field public static final int VARIANT_DEFAULT = 0; // 0x0 - field public static final int VARIANT_ELEGANT = 2; // 0x2 - } - - public static final class FontConfig.Font implements android.os.Parcelable { - method public int describeContents(); - method public android.text.FontConfig.Axis[] getAxes(); - method public java.lang.String getFontName(); - method public int getTtcIndex(); - method public android.net.Uri getUri(); - method public int getWeight(); - method public boolean isItalic(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; - } - - public final class FontManager { - method public android.text.FontConfig getSystemFonts(); - } - public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } @@ -51349,7 +51304,7 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/api/system-current.txt b/api/system-current.txt index 13e843f84f02..04c0bda29813 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9380,7 +9380,6 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; @@ -13964,7 +13963,7 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -14498,8 +14497,8 @@ package android.graphics { method public static android.graphics.Typeface.Builder obtain(); method public void recycle(); method public void reset(); - method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String); - method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]); + method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); method public android.graphics.Typeface.Builder setItalic(int); method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String); method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File); @@ -15109,6 +15108,21 @@ package android.graphics.fonts { field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR; } + public final class FontVariationAxis implements android.os.Parcelable { + ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public int describeContents(); + method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public float getStyleValue(); + method public java.lang.String getTag(); + method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR; + } + + public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception { + ctor public FontVariationAxis.InvalidFormatException(java.lang.String); + } + } package android.graphics.pdf { @@ -44495,65 +44509,6 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } - public final class FontConfig implements android.os.Parcelable { - ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]); - method public int describeContents(); - method public android.text.FontConfig.Alias[] getAliases(); - method public android.text.FontConfig.Family[] getFamilies(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; - } - - public static final class FontConfig.Alias implements android.os.Parcelable { - ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); - method public int describeContents(); - method public java.lang.String getName(); - method public java.lang.String getToName(); - method public int getWeight(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; - } - - public static final class FontConfig.Axis implements android.os.Parcelable { - ctor public FontConfig.Axis(int, float); - ctor public FontConfig.Axis(java.lang.String, float); - method public int describeContents(); - method public float getStyleValue(); - method public int getTag(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; - } - - public static final class FontConfig.Family implements android.os.Parcelable { - ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int); - method public int describeContents(); - method public android.text.FontConfig.Font[] getFonts(); - method public java.lang.String getLanguage(); - method public java.lang.String getName(); - method public int getVariant(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; - field public static final int VARIANT_COMPACT = 1; // 0x1 - field public static final int VARIANT_DEFAULT = 0; // 0x0 - field public static final int VARIANT_ELEGANT = 2; // 0x2 - } - - public static final class FontConfig.Font implements android.os.Parcelable { - method public int describeContents(); - method public android.text.FontConfig.Axis[] getAxes(); - method public java.lang.String getFontName(); - method public int getTtcIndex(); - method public android.net.Uri getUri(); - method public int getWeight(); - method public boolean isItalic(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; - } - - public final class FontManager { - method public android.text.FontConfig getSystemFonts(); - } - public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } @@ -55175,7 +55130,7 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/api/test-current.txt b/api/test-current.txt index 7b56071912ff..477687c938fa 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -8915,7 +8915,6 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -13282,7 +13281,7 @@ package android.graphics { method public void setFilterBitmap(boolean); method public void setFlags(int); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method public void setHinting(int); method public void setLetterSpacing(float); method public void setLinearText(boolean); @@ -13816,8 +13815,8 @@ package android.graphics { method public static android.graphics.Typeface.Builder obtain(); method public void recycle(); method public void reset(); - method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String); - method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]); + method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); method public android.graphics.Typeface.Builder setItalic(int); method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String); method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File); @@ -14428,6 +14427,21 @@ package android.graphics.fonts { field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR; } + public final class FontVariationAxis implements android.os.Parcelable { + ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public int describeContents(); + method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; + method public float getStyleValue(); + method public java.lang.String getTag(); + method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR; + } + + public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception { + ctor public FontVariationAxis.InvalidFormatException(java.lang.String); + } + } package android.graphics.pdf { @@ -41245,65 +41259,6 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } - public final class FontConfig implements android.os.Parcelable { - ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]); - method public int describeContents(); - method public android.text.FontConfig.Alias[] getAliases(); - method public android.text.FontConfig.Family[] getFamilies(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; - } - - public static final class FontConfig.Alias implements android.os.Parcelable { - ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); - method public int describeContents(); - method public java.lang.String getName(); - method public java.lang.String getToName(); - method public int getWeight(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; - } - - public static final class FontConfig.Axis implements android.os.Parcelable { - ctor public FontConfig.Axis(int, float); - ctor public FontConfig.Axis(java.lang.String, float); - method public int describeContents(); - method public float getStyleValue(); - method public int getTag(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; - } - - public static final class FontConfig.Family implements android.os.Parcelable { - ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int); - method public int describeContents(); - method public android.text.FontConfig.Font[] getFonts(); - method public java.lang.String getLanguage(); - method public java.lang.String getName(); - method public int getVariant(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; - field public static final int VARIANT_COMPACT = 1; // 0x1 - field public static final int VARIANT_DEFAULT = 0; // 0x0 - field public static final int VARIANT_ELEGANT = 2; // 0x2 - } - - public static final class FontConfig.Font implements android.os.Parcelable { - method public int describeContents(); - method public android.text.FontConfig.Axis[] getAxes(); - method public java.lang.String getFontName(); - method public int getTtcIndex(); - method public android.net.Uri getUri(); - method public int getWeight(); - method public boolean isItalic(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; - } - - public final class FontManager { - method public android.text.FontConfig getSystemFonts(); - } - public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } @@ -51740,7 +51695,7 @@ package android.widget { method public void setExtractedText(android.view.inputmethod.ExtractedText); method public void setFilters(android.text.InputFilter[]); method public void setFontFeatureSettings(java.lang.String); - method public boolean setFontVariationSettings(java.lang.String); + method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException; method protected boolean setFrame(int, int, int, int); method public void setFreezesText(boolean); method public void setGravity(int); diff --git a/compiled-classes-phone b/compiled-classes-phone index ea8f4a4d87fa..1a19b2ce2de5 100644 --- a/compiled-classes-phone +++ b/compiled-classes-phone @@ -4061,7 +4061,6 @@ android.text.FontConfig$Family android.text.FontConfig$Family$1 android.text.FontConfig$Font android.text.FontConfig$Font$1 -android.text.FontManager android.text.GetChars android.text.GraphicsOperations android.text.Html @@ -5501,8 +5500,6 @@ com.android.internal.content.PackageHelper com.android.internal.content.PackageMonitor com.android.internal.content.ReferrerIntent com.android.internal.content.ReferrerIntent$1 -com.android.internal.font.IFontManager -com.android.internal.font.IFontManager$Stub com.android.internal.graphics.drawable.AnimationScaleListDrawable com.android.internal.graphics.drawable.AnimationScaleListDrawable$AnimationScaleListState com.android.internal.hardware.AmbientDisplayConfiguration diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index f719749cc9f9..6b05bdff5d1e 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -125,7 +125,6 @@ import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.text.FontManager; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -141,7 +140,6 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.app.ISoundTriggerService; import com.android.internal.appwidget.IAppWidgetService; -import com.android.internal.font.IFontManager; import com.android.internal.os.IDropBoxManagerService; import com.android.internal.policy.PhoneLayoutInflater; @@ -820,14 +818,6 @@ final class SystemServiceRegistry { return new IncidentManager(ctx); }}); - registerService(Context.FONT_SERVICE, FontManager.class, - new CachedServiceFetcher<FontManager>() { - @Override - public FontManager createService(ContextImpl ctx) - throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE); - return new FontManager(IFontManager.Stub.asInterface(b)); - }}); registerService(Context.AUTOFILL_MANAGER_SERVICE, AutofillManager.class, new CachedServiceFetcher<AutofillManager>() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index dbbfe308868c..9a4fe1a4a616 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3870,11 +3870,6 @@ public abstract class Context { public static final String DEVICE_IDENTIFIERS_SERVICE = "device_identifiers"; /** - * Service that provides System font data. - */ - public static final String FONT_SERVICE = "font"; - - /** * Service to report a system health "incident" * @hide */ diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java index 14d3ad790b1d..8537d8f1ea84 100644 --- a/core/java/android/text/FontConfig.java +++ b/core/java/android/text/FontConfig.java @@ -21,7 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.graphics.FontListParser; +import android.graphics.fonts.FontVariationAxis; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -31,6 +31,7 @@ import java.lang.annotation.Retention; /** * Font configuration descriptions for System fonts. + * @hide */ public final class FontConfig implements Parcelable { private final @NonNull Family[] mFamilies; @@ -84,78 +85,12 @@ public final class FontConfig implements Parcelable { }; /** - * Class that holds information about a Font axis. - */ - public static final class Axis implements Parcelable { - private final int mTag; - private final float mStyleValue; - - public Axis(int tag, float styleValue) { - mTag = tag; - mStyleValue = styleValue; - } - - public Axis(@NonNull String tagString, float styleValue) { - if (!FontListParser.isValidTag(tagString)) { - throw new IllegalArgumentException("Invalid tag pattern: " + tagString); - } - mTag = FontListParser.makeTag(tagString); - mStyleValue = styleValue; - } - - /** - * Returns the variable font axis tag associated to this axis. - */ - public int getTag() { - return mTag; - } - - /** - * Returns the style value associated to the given axis for this font. - */ - public float getStyleValue() { - return mStyleValue; - } - - /** - * @hide - */ - public Axis(Parcel in) { - mTag = in.readInt(); - mStyleValue = in.readFloat(); - } - - @Override - public void writeToParcel(Parcel out, int flag) { - out.writeInt(mTag); - out.writeFloat(mStyleValue); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator<Axis> CREATOR = new Creator<Axis>() { - @Override - public Axis createFromParcel(Parcel in) { - return new Axis(in); - } - - @Override - public Axis[] newArray(int size) { - return new Axis[size]; - } - }; - } - - /** * Class that holds information about a Font. */ public static final class Font implements Parcelable { private final @NonNull String mFontName; private final int mTtcIndex; - private final @NonNull Axis[] mAxes; + private final @NonNull FontVariationAxis[] mAxes; private final int mWeight; private final boolean mIsItalic; private Uri mUri; @@ -163,8 +98,8 @@ public final class FontConfig implements Parcelable { /** * @hide */ - public Font(@NonNull String fontName, int ttcIndex, @NonNull Axis[] axes, int weight, - boolean isItalic) { + public Font(@NonNull String fontName, int ttcIndex, @NonNull FontVariationAxis[] axes, + int weight, boolean isItalic) { mFontName = fontName; mTtcIndex = ttcIndex; mAxes = axes; @@ -189,7 +124,7 @@ public final class FontConfig implements Parcelable { /** * Returns the list of axes associated to this font. */ - public @NonNull Axis[] getAxes() { + public @NonNull FontVariationAxis[] getAxes() { return mAxes; } @@ -230,7 +165,7 @@ public final class FontConfig implements Parcelable { public Font(Parcel in) { mFontName = in.readString(); mTtcIndex = in.readInt(); - mAxes = in.createTypedArray(Axis.CREATOR); + mAxes = in.createTypedArray(FontVariationAxis.CREATOR); mWeight = in.readInt(); mIsItalic = in.readInt() == 1; mUri = in.readTypedObject(Uri.CREATOR); diff --git a/core/java/android/text/FontManager.java b/core/java/android/text/FontManager.java deleted file mode 100644 index b61cbf3018ef..000000000000 --- a/core/java/android/text/FontManager.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text; - -import android.os.RemoteException; - -import com.android.internal.font.IFontManager; - -/** - * Interact with the Font service. - */ -public final class FontManager { - private static final String TAG = "FontManager"; - - private final IFontManager mService; - - /** - * @hide - */ - public FontManager(IFontManager service) { - mService = service; - } - - /** - * Retrieve the system fonts data. This loads the fonts.xml data if needed and loads all system - * fonts in to memory, providing file descriptors for them. - */ - public FontConfig getSystemFonts() { - try { - return mService.getSystemFonts(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } -} diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/android/text/FontVariationAxis.aidl index 52a626288caf..d5d52c26024f 100644 --- a/core/java/com/android/internal/font/IFontManager.aidl +++ b/core/java/android/text/FontVariationAxis.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2017 The Android Open Source Project +/** + * Copyright (c) 2017, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,14 +14,6 @@ * limitations under the License. */ -package com.android.internal.font; - -import android.text.FontConfig; +package android.text; -/** - * Interface to the font manager. - * @hide - */ -interface IFontManager { - FontConfig getSystemFonts(); -} +parcelable FontVariationAxis; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 6f8df36b7bf5..b38366393a4d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -56,6 +56,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.fonts.FontVariationAxis; import android.os.AsyncTask; import android.os.Bundle; import android.os.LocaleList; @@ -3808,10 +3809,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * TextView. This function also returns true for empty settings string. Otherwise * returns false. * + * @throws FontVariationAxis.InvalidFormatException + * If given string is not a valid font variation settings format. + * * @see #getFontVariationSettings() * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings() */ - public boolean setFontVariationSettings(@Nullable String fontVariationSettings) { + public boolean setFontVariationSettings(@Nullable String fontVariationSettings) + throws FontVariationAxis.InvalidFormatException { final String existingSettings = mTextPaint.getFontVariationSettings(); if (fontVariationSettings == existingSettings || (fontVariationSettings != null diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp index 91fec2a75e2c..3bcf0c7fb354 100644 --- a/core/jni/android/graphics/FontUtils.cpp +++ b/core/jni/android/graphics/FontUtils.cpp @@ -55,7 +55,7 @@ void init_FontUtils(JNIEnv* env) { gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;"); gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I"); - jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis"); + jclass axisClass = FindClassOrDie(env, "android/graphics/fonts/FontVariationAxis"); gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I"); gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F"); } diff --git a/core/tests/coretests/src/android/graphics/VariationParserTest.java b/core/tests/coretests/src/android/graphics/VariationParserTest.java deleted file mode 100644 index fdabb130115c..000000000000 --- a/core/tests/coretests/src/android/graphics/VariationParserTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.graphics; - -import android.test.suitebuilder.annotation.SmallTest; -import android.text.FontConfig; - -import junit.framework.TestCase; - -import java.util.List; - - -public class VariationParserTest extends TestCase { - - @SmallTest - public void testParseFontVariationSetting() { - int tag = FontListParser.makeTag("wdth"); - List<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings("'wdth' 1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("\"wdth\" 100"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(100.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings(" 'wdth' 100"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(100.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(0.5f, axes.get(0).getStyleValue()); - - tag = FontListParser.makeTag("AX "); - axes = FontListParser.parseFontVariationSettings("'AX ' 1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("'AX '\t1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("'AX '\n1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("'AX '\r1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - axes = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1"); - assertEquals(tag, axes.get(0).getTag()); - assertEquals(1.0f, axes.get(0).getStyleValue()); - - // Test for invalid input - axes = FontListParser.parseFontVariationSettings(""); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("invalid_form"); - assertEquals(0, axes.size()); - - // Test with invalid tag - axes = FontListParser.parseFontVariationSettings("'' 1"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'invalid' 1"); - assertEquals(0, axes.size()); - - // Test with invalid styleValue - axes = FontListParser.parseFontVariationSettings("'wdth' "); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' x"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' \t"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'wdth' \n\r"); - assertEquals(0, axes.size()); - } - - @SmallTest - public void testParseFontVariationStyleSettings() { - List<FontConfig.Axis> axes = - FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1"); - int tag1 = FontListParser.makeTag("wdth"); - int tag2 = FontListParser.makeTag("AX "); - assertEquals(tag1, axes.get(0).getTag()); - assertEquals(10.0f, axes.get(0).getStyleValue()); - assertEquals(tag2, axes.get(1).getTag()); - assertEquals(1.0f, axes.get(1).getStyleValue()); - - // Test only spacers are allowed before tag - axes = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1"); - tag1 = FontListParser.makeTag("wdth"); - assertEquals(tag1, axes.get(0).getTag()); - assertEquals(10.0f, axes.get(0).getStyleValue()); - assertEquals(1, axes.size()); - } - - @SmallTest - public void testInvalidTagCharacters() { - List<FontConfig.Axis> axes = - FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10"); - assertEquals(0, axes.size()); - axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10"); - assertEquals(0, axes.size()); - } - - @SmallTest - public void testMakeTag() { - assertEquals(0x77647468, FontListParser.makeTag("wdth")); - assertEquals(0x41582020, FontListParser.makeTag("AX ")); - assertEquals(0x20202020, FontListParser.makeTag(" ")); - } -} diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java new file mode 100644 index 000000000000..bcc47e1fc201 --- /dev/null +++ b/core/tests/coretests/src/android/text/VariationParserTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text; + +import android.graphics.fonts.FontVariationAxis; +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +public class VariationParserTest extends TestCase { + private static final String[] INVALID_STYLE_VALUES = { + "", "x", "\t", "\n" + }; + + @SmallTest + public void testFromFontVariationSetting_InvalidStyleValue() { + // Test with invalid styleValue + for (String invalidStyle : INVALID_STYLE_VALUES) { + try { + FontVariationAxis.fromFontVariationSettings("'wdth' " + invalidStyle); + fail(); + } catch (FontVariationAxis.InvalidFormatException e) { + // pass + } + } + for (String invalidStyle : INVALID_STYLE_VALUES) { + try { + FontVariationAxis.fromFontVariationSettings("'wght' 1, 'wdth' " + invalidStyle); + fail(); + } catch (FontVariationAxis.InvalidFormatException e) { + // pass + } + } + } + + @SmallTest + public void testOpenTypeTagValue() throws FontVariationAxis.InvalidFormatException { + assertEquals(0x77647468, (new FontVariationAxis("wdth", 0).getOpenTypeTagValue())); + assertEquals(0x41582020, (new FontVariationAxis("AX ", 0).getOpenTypeTagValue())); + assertEquals(0x20202020, (new FontVariationAxis(" ", 0).getOpenTypeTagValue())); + } +} diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml index 76c29a9bf971..3dab1f7e20e1 100644 --- a/data/fonts/fonts.xml +++ b/data/fonts/fonts.xml @@ -3,15 +3,10 @@ WARNING: Parsing of this file by third-party apps is not supported. The file, and the font files it refers to, will be renamed and/or moved out from their respective location in the next Android release, and/or the - format or syntax of the file may change significantly. You must not - parse this file for information about system fonts. Instead, you must - call android.text.FontManager#getSystemFonts(). For example, it can be - called as context.getSystemService(FontManager.class).getSystemFonts(). - Note that the returned FontConfig includes data on all the defined font - families and all the details about weight, style, etc. It also provides - an open file descriptor to each font file. Note that callers of the API - should ensure they close the given file descriptors once they are done - using them. + format or syntax of the file may change significantly. If you parse this + file for information about system fonts, do it at your own risk. Your + application will almost certainly break with the next major Android + release. In this file, all fonts without names are added to the default list. Fonts are chosen based on a match: full BCP-47 language tag including diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 6214ba6741c9..4b1b0c641807 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -17,6 +17,7 @@ package android.graphics; import android.content.res.AssetManager; +import android.graphics.fonts.FontVariationAxis; import android.text.FontConfig; import android.util.Log; import dalvik.annotation.optimization.CriticalNative; @@ -81,7 +82,7 @@ public class FontFamily { } } - public boolean addFont(String path, int ttcIndex, FontConfig.Axis[] axes, int weight, + public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight, int italic) { if (mBuilderPtr == 0) { throw new IllegalStateException("Unable to call addFont after freezing."); @@ -91,8 +92,8 @@ public class FontFamily { long fontSize = fileChannel.size(); ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize); if (axes != null) { - for (FontConfig.Axis axis : axes) { - nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue()); + for (FontVariationAxis axis : axes) { + nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue()); } } return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic); @@ -102,14 +103,14 @@ public class FontFamily { } } - public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontConfig.Axis[] axes, + public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes, int weight, int italic) { if (mBuilderPtr == 0) { throw new IllegalStateException("Unable to call addFontWeightStyle after freezing."); } if (axes != null) { - for (FontConfig.Axis axis : axes) { - nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue()); + for (FontVariationAxis axis : axes) { + nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue()); } } return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic); @@ -129,13 +130,13 @@ public class FontFamily { */ public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic, - FontConfig.Axis[] axes) { + FontVariationAxis[] axes) { if (mBuilderPtr == 0) { throw new IllegalStateException("Unable to call addFontFromAsset after freezing."); } if (axes != null) { - for (FontConfig.Axis axis : axes) { - nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue()); + for (FontVariationAxis axis : axes) { + nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue()); } } return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight, diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index ff9f11dae4dc..1a4f225c6267 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -17,6 +17,7 @@ package android.graphics; import android.text.FontConfig; +import android.graphics.fonts.FontVariationAxis; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; @@ -50,72 +51,6 @@ public class FontListParser { } } - // Note that a well-formed variation contains a four-character tag and a float as styleValue, - // with spacers in between. The tag is enclosd either by double quotes or single quotes. - @VisibleForTesting - public static ArrayList<FontConfig.Axis> parseFontVariationSettings(@Nullable String settings) { - ArrayList<FontConfig.Axis> axisList = new ArrayList<>(); - if (settings == null) { - return axisList; - } - String[] settingList = settings.split(","); - settingLoop: - for (String setting : settingList) { - int pos = 0; - while (pos < setting.length()) { - char c = setting.charAt(pos); - if (c == '\'' || c == '"') { - break; - } else if (!isSpacer(c)) { - continue settingLoop; // Only spacers are allowed before tag appeared. - } - pos++; - } - if (pos + 7 > setting.length()) { - continue; // 7 is the minimum length of tag-style value pair text. - } - if (setting.charAt(pos) != setting.charAt(pos + 5)) { - continue; // Tag should be wrapped with double or single quote. - } - String tagString = setting.substring(pos + 1, pos + 5); - if (!TAG_PATTERN.matcher(tagString).matches()) { - continue; // Skip incorrect format tag. - } - pos += 6; - while (pos < setting.length()) { - if (!isSpacer(setting.charAt(pos++))) { - break; // Skip spacers between the tag and the styleValue. - } - } - // Skip invalid styleValue - float styleValue; - String valueString = setting.substring(pos - 1); - if (!STYLE_VALUE_PATTERN.matcher(valueString).matches()) { - continue; // Skip incorrect format styleValue. - } - try { - styleValue = Float.parseFloat(valueString); - } catch (NumberFormatException e) { - continue; // ignoreing invalid number format - } - int tag = makeTag(tagString); - axisList.add(new FontConfig.Axis(tag, styleValue)); - } - return axisList; - } - - public static int makeTag(String tagString) { - char c1 = tagString.charAt(0); - char c2 = tagString.charAt(1); - char c3 = tagString.charAt(2); - char c4 = tagString.charAt(3); - return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4; - } - - private static boolean isSpacer(char c) { - return c == ' ' || c == '\r' || c == '\t' || c == '\n'; - } - private static FontConfig readFamilies(XmlPullParser parser) throws XmlPullParserException, IOException { List<FontConfig.Family> families = new ArrayList<>(); @@ -172,7 +107,7 @@ public class FontListParser { throws XmlPullParserException, IOException { String indexStr = parser.getAttributeValue(null, "index"); int index = indexStr == null ? 0 : Integer.parseInt(indexStr); - List<FontConfig.Axis> axes = new ArrayList<FontConfig.Axis>(); + List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>(); String weightStr = parser.getAttributeValue(null, "weight"); int weight = weightStr == null ? 400 : Integer.parseInt(weightStr); boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style")); @@ -191,47 +126,20 @@ public class FontListParser { } String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll(""); return new FontConfig.Font(sanitizedName, index, - axes.toArray(new FontConfig.Axis[axes.size()]), weight, isItalic); + axes.toArray(new FontVariationAxis[axes.size()]), weight, isItalic); } - /** The 'tag' attribute value is read as four character values between U+0020 and U+007E - * inclusive. - */ - private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}"); - - public static boolean isValidTag(String tagString) { - if (tagString == null || tagString.length() != 4) { - return false; - } - return TAG_PATTERN.matcher(tagString).matches(); - } - - /** The 'styleValue' attribute has an optional leading '-', followed by '<digits>', - * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9]. - */ - private static final Pattern STYLE_VALUE_PATTERN = - Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))"); - - private static FontConfig.Axis readAxis(XmlPullParser parser) + private static FontVariationAxis readAxis(XmlPullParser parser) throws XmlPullParserException, IOException { - int tag = 0; String tagStr = parser.getAttributeValue(null, "tag"); - if (isValidTag(tagStr)) { - tag = makeTag(tagStr); - } else { - throw new XmlPullParserException("Invalid tag attribute value.", parser, null); - } - - float styleValue = 0; String styleValueStr = parser.getAttributeValue(null, "stylevalue"); - if (styleValueStr != null && STYLE_VALUE_PATTERN.matcher(styleValueStr).matches()) { - styleValue = Float.parseFloat(styleValueStr); - } else { - throw new XmlPullParserException("Invalid styleValue attribute value.", parser, null); - } - skip(parser); // axis tag is empty, ignore any contents and consume end tag - return new FontConfig.Axis(tag, styleValue); + try { + return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr)); + } catch (FontVariationAxis.InvalidFormatException e) { + // Treat as system failure since system preinstalled font setting has invalid format. + throw new RuntimeException(e); + } } private static FontConfig.Alias readAlias(XmlPullParser parser) diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index c4f7dc39b4bd..828729a064e9 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -20,6 +20,7 @@ import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Size; import android.graphics.FontListParser; +import android.graphics.fonts.FontVariationAxis; import android.os.LocaleList; import android.text.FontConfig; import android.text.GraphicsOperations; @@ -1551,8 +1552,11 @@ public class Paint { * @return true if the given settings is effective to at least one font file underlying this * typeface. This function also returns true for empty settings string. Otherwise * returns false + * @throws FontVariationAxis.InvalidFormatException + * If given string is not a valid font variation settings format. */ - public boolean setFontVariationSettings(String settings) { + public boolean setFontVariationSettings(String settings) + throws FontVariationAxis.InvalidFormatException { settings = TextUtils.nullIfEmpty(settings); if (settings == mFontVariationSettings || (settings != null && settings.equals(mFontVariationSettings))) { @@ -1566,11 +1570,10 @@ public class Paint { return true; } - final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(settings); - final ArrayList<FontConfig.Axis> filteredAxes = new ArrayList<FontConfig.Axis>(); - for (int i = 0; i < axes.size(); ++i) { - final FontConfig.Axis axis = axes.get(i); - if (mTypeface.isSupportedAxes(axis.getTag())) { + FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings); + final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>(); + for (final FontVariationAxis axis : axes) { + if (mTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) { filteredAxes.add(axis); } } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 8c3a2e8068ca..560d29f1934d 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -32,6 +32,7 @@ import android.content.res.AssetManager; import android.graphics.FontListParser; import android.graphics.fonts.FontRequest; import android.graphics.fonts.FontResult; +import android.graphics.fonts.FontVariationAxis; import android.os.Bundle; import android.os.Handler; import android.os.ParcelFileDescriptor; @@ -358,11 +359,15 @@ public class Typeface { FileChannel.MapMode.READ_ONLY, 0, fontSize); int style = result.getStyle(); int weight = (style & BOLD) != 0 ? 700 : 400; - final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings( - result.getFontVariationSettings()); - if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(), - axes.toArray(new FontConfig.Axis[axes.size()]), weight, - (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) { + FontVariationAxis[] axes = null; + try { + axes = FontVariationAxis.fromFontVariationSettings( + result.getFontVariationSettings()); + } catch (FontVariationAxis.InvalidFormatException e) { + // TODO: Nice to pass FontVariationAxis[] directly instead of string. + } + if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(), axes, weight, + (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) { Log.e(TAG, "Error creating font " + request.getQuery()); callback.onTypefaceRequestFailed( FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); @@ -514,7 +519,7 @@ public class Typeface { public static final int ITALIC = 1; private int mTtcIndex; - private FontConfig.Axis[] mAxes; + private FontVariationAxis[] mAxes; private AssetManager mAssetManager; private String mPath; @@ -682,15 +687,16 @@ public class Typeface { * Sets a font variation settings. * * @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}. + * @throws FontVariationAxis.InvalidFormatException If given string is not a valid font + * variation settings format. */ - public Builder setFontVariationSettings(@Nullable String variationSettings) { + public Builder setFontVariationSettings(@Nullable String variationSettings) + throws FontVariationAxis.InvalidFormatException { checkNotRecycled(); if (mAxes != null) { throw new IllegalStateException("Font variation settings are already set."); } - final List<FontConfig.Axis> axesList = FontListParser.parseFontVariationSettings( - variationSettings); - mAxes = axesList.toArray(new FontConfig.Axis[axesList.size()]); + mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings); return this; } @@ -699,7 +705,7 @@ public class Typeface { * * @param axes An array of font variation axis tag-value pairs. */ - public Builder setFontVariationSettings(@Nullable FontConfig.Axis[] axes) { + public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) { checkNotRecycled(); if (mAxes != null) { throw new IllegalStateException("Font variation settings are already set."); @@ -718,7 +724,7 @@ public class Typeface { * @return Unique id for a given AssetManager and asset path. */ private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex, - @Nullable FontConfig.Axis[] axes) { + @Nullable FontVariationAxis[] axes) { final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers(); final StringBuilder builder = new StringBuilder(); final int size = pkgs.size(); @@ -731,8 +737,8 @@ public class Typeface { builder.append(Integer.toString(ttcIndex)); builder.append("-"); if (axes != null) { - for (FontConfig.Axis axis : axes) { - builder.append(Integer.toHexString(axis.getTag())); + for (FontVariationAxis axis : axes) { + builder.append(axis.getTag()); builder.append("-"); builder.append(Float.toString(axis.getStyleValue())); } @@ -865,7 +871,7 @@ public class Typeface { /** @hide */ public static Typeface createFromTypefaceWithVariation(Typeface family, - List<FontConfig.Axis> axes) { + List<FontVariationAxis> axes) { final long ni = family == null ? 0 : family.native_instance; return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes)); } @@ -1162,9 +1168,9 @@ public class Typeface { } private static native long nativeCreateFromTypeface(long native_instance, int style); - // TODO: clean up: change List<FontConfig.Axis> to FontConfig.Axis[] + // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[] private static native long nativeCreateFromTypefaceWithVariation( - long native_instance, List<FontConfig.Axis> axes); + long native_instance, List<FontVariationAxis> axes); private static native long nativeCreateWeightAlias(long native_instance, int weight); private static native void nativeUnref(long native_instance); private static native int nativeGetStyle(long native_instance); diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java new file mode 100644 index 000000000000..91ec0e8df912 --- /dev/null +++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics.fonts; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.regex.Pattern; + +/** + * Class that holds information about single font variation axis. + */ +public final class FontVariationAxis implements Parcelable { + private final int mTag; + private final String mTagString; + private final float mStyleValue; + + /** + * Construct FontVariationAxis. + * + * The axis tag must contain four ASCII characters. Tag string that are longer or shorter than + * four characters, or contains characters outside of U+0020..U+007E are invalid. + * + * @throws {@link InvalidFormatException} If given tag string is invalid. + */ + public FontVariationAxis(@NonNull String tagString, float styleValue) + throws InvalidFormatException { + if (!isValidTag(tagString)) { + throw new InvalidFormatException("Invalid tag pattern: " + tagString); + } + mTag = makeTag(tagString); + mTagString = tagString; + mStyleValue = styleValue; + } + + /** + * Returns the OpenType style tag value. + * @hide + */ + public int getOpenTypeTagValue() { + return mTag; + } + + /** + * Returns the variable font axis tag associated to this axis. + */ + public String getTag() { + return mTagString; + } + + /** + * Returns the style value associated to the given axis for this font. + */ + public float getStyleValue() { + return mStyleValue; + } + + /** + * @hide + */ + public FontVariationAxis(Parcel in) { + mTag = in.readInt(); + mTagString = in.readString(); + mStyleValue = in.readFloat(); + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeInt(mTag); + out.writeString(mTagString); + out.writeFloat(mStyleValue); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<FontVariationAxis> CREATOR = new Creator<FontVariationAxis>() { + @Override + public FontVariationAxis createFromParcel(Parcel in) { + return new FontVariationAxis(in); + } + + @Override + public FontVariationAxis[] newArray(int size) { + return new FontVariationAxis[size]; + } + }; + + /** + * Returns a valid font variation setting string for this object. + */ + @Override + public @NonNull String toString() { + return "'" + mTagString + "' " + Float.toString(mStyleValue); + } + + /** + * The 'tag' attribute value is read as four character values between U+0020 and U+007E + * inclusive. + */ + private static final Pattern TAG_PATTERN = Pattern.compile("[\u0020-\u007E]{4}"); + + /** + * Returns true if 'tagString' is valid for font variation axis tag. + */ + private static boolean isValidTag(String tagString) { + return tagString != null && TAG_PATTERN.matcher(tagString).matches(); + } + + /** + * The 'styleValue' attribute has an optional leading '-', followed by '<digits>', + * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9]. + */ + private static final Pattern STYLE_VALUE_PATTERN = + Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))"); + + private static boolean isValidValueFormat(String valueString) { + return valueString != null && STYLE_VALUE_PATTERN.matcher(valueString).matches(); + } + + /** @hide */ + public static int makeTag(String tagString) { + final char c1 = tagString.charAt(0); + final char c2 = tagString.charAt(1); + final char c3 = tagString.charAt(2); + final char c4 = tagString.charAt(3); + return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4; + } + + /** + * An exception indicates that the format of font variation settings is invalid. + */ + public static class InvalidFormatException extends Exception { + public InvalidFormatException(String message) { + super(message); + } + }; + + /** + * Construct FontVariationAxis array from font variation settings. + * + * The settings string is constructed from multiple pairs of axis tag and style values. The axis + * tag must contain four ASCII characters and must be wrapped with single quotes (U+0027) or + * double quotes (U+0022). Axis strings that are longer or shorter than four characters, or + * contain characters outside of U+0020..U+007E are invalid. If a specified axis name is not + * defined in the font, the settings will be ignored. + * + * <pre> + * FontVariationAxis.fromFontVariationSettings("'wdth' 1.0"); + * FontVariationAxis.fromFontVariationSettings("'AX ' 1.0, 'FB ' 2.0"); + * </pre> + * + * @param settings font variation settings. + * @return FontVariationAxis[] the array of parsed font variation axis. {@code null} if settings + * has no font variation settings. + * @throws InvalidFormatException If given string is not a valid font variation settings format. + */ + public static @Nullable FontVariationAxis[] fromFontVariationSettings(@Nullable String settings) + throws InvalidFormatException { + if (settings == null || settings.isEmpty()) { + return null; + } + final ArrayList<FontVariationAxis> axisList = new ArrayList<>(); + final int length = settings.length(); + for (int i = 0; i < length; i++) { + final char c = settings.charAt(i); + if (Character.isWhitespace(c)) { + continue; + } + if (!(c == '\'' || c == '"') || length < i + 6 || settings.charAt(i + 5) != c) { + throw new InvalidFormatException( + "Tag should be wrapped with double or single quote: " + settings); + } + final String tagString = settings.substring(i + 1, i + 5); + + i += 6; // Move to end of tag. + int endOfValueString = settings.indexOf(',', i); + if (endOfValueString == -1) { + endOfValueString = length; + } + final float value; + try { + // Float.parseFloat ignores leading/trailing whitespaces. + value = Float.parseFloat(settings.substring(i, endOfValueString)); + } catch (NumberFormatException e) { + throw new InvalidFormatException("Failed to parse float string: " + e.getMessage()); + } + axisList.add(new FontVariationAxis(tagString, value)); + i = endOfValueString; + } + if (axisList.isEmpty()) { + return null; + } + return axisList.toArray(new FontVariationAxis[0]); + } + + /** + * Stringify the array of FontVariationAxis. + * + * @param axes an array of FontVariationAxis. + * @return String a valid font variation settings string. + */ + public static @NonNull String toFontVariationSettings(@Nullable FontVariationAxis[] axes) { + if (axes == null || axes.length == 0) { + return ""; + } + return TextUtils.join(",", axes); + } +} + diff --git a/preloaded-classes b/preloaded-classes index a72a04272cba..892c59394855 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -1817,7 +1817,6 @@ android.text.FontConfig$Family android.text.FontConfig$Family$1 android.text.FontConfig$Font android.text.FontConfig$Font$1 -android.text.FontManager android.text.GetChars android.text.GraphicsOperations android.text.Html diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java deleted file mode 100644 index f1726473c591..000000000000 --- a/services/core/java/com/android/server/FontManagerService.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.content.Context; -import android.graphics.FontListParser; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.text.FontConfig; -import android.util.Slog; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.font.IFontManager; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -public class FontManagerService extends IFontManager.Stub { - private static final String TAG = "FontManagerService"; - private static final String FONTS_CONFIG = "/system/etc/fonts.xml"; - private static final String SYSTEM_FONT_DIR = "/system/fonts/"; - - @GuardedBy("mLock") - private FontConfig mConfig; - private final Object mLock = new Object(); - - public static final class Lifecycle extends SystemService { - private final FontManagerService mService; - - public Lifecycle(Context context) { - super(context); - mService = new FontManagerService(); - } - - @Override - public void onStart() { - try { - publishBinderService(Context.FONT_SERVICE, mService); - } catch (Throwable t) { - // Starting this service is not critical to the running of this device and should - // therefore not crash the device. If it fails, log the error and continue. - Slog.e(TAG, "Could not start the FontManagerService.", t); - } - } - } - - @Override - public FontConfig getSystemFonts() { - synchronized (mLock) { - if (mConfig != null) { - return mConfig; - } - - mConfig = loadFromSystem(); - if (mConfig == null) { - return null; - } - - for (FontConfig.Family family : mConfig.getFamilies()) { - for (FontConfig.Font font : family.getFonts()) { - File fontFile = new File(SYSTEM_FONT_DIR, font.getFontName()); - font.setUri(Uri.fromFile(fontFile)); - } - } - - return mConfig; - } - } - - private FontConfig loadFromSystem() { - File configFilename = new File(FONTS_CONFIG); - try { - FileInputStream fontsIn = new FileInputStream(configFilename); - return FontListParser.parse(fontsIn); - } catch (IOException | XmlPullParserException e) { - Slog.e(TAG, "Error opening " + configFilename, e); - } - return null; - } - - public FontManagerService() { - } -} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index da49eb37ebec..d2b84e8a99d9 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1014,12 +1014,6 @@ public final class SystemServer { traceEnd(); } - if (!disableNonCoreServices) { - traceBeginAndSlog("StartFontServiceManager"); - mSystemServiceManager.startService(FontManagerService.Lifecycle.class); - traceEnd(); - } - if (!disableNonCoreServices && !disableTextServices) { traceBeginAndSlog("StartTextServicesManager"); mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class); diff --git a/services/profile-classes b/services/profile-classes index 1b304e14d8fd..b0d2da7aeba6 100644 --- a/services/profile-classes +++ b/services/profile-classes @@ -2481,7 +2481,6 @@ Landroid/text/FontConfig$Family; Landroid/text/FontConfig$Family$1; Landroid/text/FontConfig$Font; Landroid/text/FontConfig$Font$1; -Landroid/text/FontManager; Landroid/text/format/DateFormat; Landroid/text/format/Time; Landroid/text/format/Time$TimeCalculator; @@ -3132,8 +3131,6 @@ Lcom/android/internal/content/PackageHelper; Lcom/android/internal/content/PackageMonitor; Lcom/android/internal/content/ReferrerIntent; Lcom/android/internal/content/ReferrerIntent$1; -Lcom/android/internal/font/IFontManager; -Lcom/android/internal/font/IFontManager$Stub; Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable; Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable$AnimationScaleListState; Lcom/android/internal/hardware/AmbientDisplayConfiguration; @@ -4377,8 +4374,6 @@ Lcom/android/server/firewall/StringFilter$7; Lcom/android/server/firewall/StringFilter$8; Lcom/android/server/firewall/StringFilter$9; Lcom/android/server/firewall/StringFilter$ValueProvider; -Lcom/android/server/FontManagerService; -Lcom/android/server/FontManagerService$Lifecycle; Lcom/android/server/GestureLauncherService; Lcom/android/server/GestureLauncherService$1; Lcom/android/server/GestureLauncherService$2; diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index 7fe464abbf32..a21fe68e9003 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.AssetManager; import android.content.res.BridgeAssetManager; +import android.graphics.fonts.FontVariationAxis; import android.text.FontConfig; import java.awt.Font; @@ -250,7 +251,7 @@ public class FontFamily_Delegate { // ---- delegate methods ---- @LayoutlibDelegate /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex, - FontConfig.Axis[] axes, int weight, int italic) { + FontVariationAxis[] axes, int weight, int italic) { if (thisFontFamily.mBuilderPtr == 0) { assert false : "Unable to call addFont after freezing."; return false; diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index 80e3bada8ca3..c7818a3a9974 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -23,6 +23,7 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.annotation.NonNull; import android.graphics.FontFamily_Delegate.FontVariant; +import android.graphics.fonts.FontVariationAxis; import android.text.FontConfig; import java.awt.Font; @@ -163,7 +164,7 @@ public final class Typeface_Delegate { @LayoutlibDelegate /*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance, - List<FontConfig.Axis> axes) { + List<FontVariationAxis> axes) { long newInstance = nativeCreateFromTypeface(native_instance, 0); if (newInstance != 0) { |