| /* |
| * 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 static java.lang.annotation.RetentionPolicy.SOURCE; |
| |
| import android.annotation.CurrentTimeMillisLong; |
| import android.annotation.IntDef; |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.SystemApi; |
| import android.annotation.TestApi; |
| import android.compat.annotation.UnsupportedAppUsage; |
| import android.graphics.fonts.FontStyle; |
| import android.graphics.fonts.FontVariationAxis; |
| import android.os.Build; |
| import android.os.LocaleList; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| import java.io.File; |
| import java.lang.annotation.Retention; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Objects; |
| |
| |
| /** |
| * Font configuration descriptions for System fonts. |
| * |
| * FontConfig represents the configuration for the fonts installed on the system. It is made of list |
| * of font families and aliases. |
| * |
| * @see FontFamily |
| * @see Alias |
| * @hide |
| */ |
| @SystemApi |
| @TestApi |
| public final class FontConfig implements Parcelable { |
| private final @NonNull List<FontFamily> mFamilies; |
| private final @NonNull List<Alias> mAliases; |
| private final long mLastModifiedTimeMillis; |
| private final int mConfigVersion; |
| |
| /** |
| * Construct a FontConfig instance. |
| * |
| * @param families a list of font families. |
| * @param aliases a list of aliases. |
| * |
| * @hide Only system server can create this instance and passed via IPC. |
| */ |
| public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases, |
| long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion) { |
| mFamilies = families; |
| mAliases = aliases; |
| mLastModifiedTimeMillis = lastModifiedTimeMillis; |
| mConfigVersion = configVersion; |
| } |
| |
| /** |
| * Returns the ordered list of font families available in the system. |
| * |
| * @return a list of font families. |
| * @see FontFamily |
| */ |
| public @NonNull List<FontFamily> getFontFamilies() { |
| return mFamilies; |
| } |
| |
| /** |
| * Returns the list of aliases for mapping font families with other names. |
| * |
| * @return a list of font families. |
| * @see Alias |
| */ |
| public @NonNull List<Alias> getAliases() { |
| return mAliases; |
| } |
| |
| /** |
| * Returns the last modified time in milliseconds. |
| * |
| * This is a value of {@link System#currentTimeMillis()} when the system font configuration was |
| * modified last time. |
| * |
| * If there is no update, this return 0. |
| */ |
| public @CurrentTimeMillisLong long getLastModifiedTimeMillis() { |
| return mLastModifiedTimeMillis; |
| } |
| |
| /** |
| * Returns the monotonically increasing config version value. |
| * |
| * The config version is reset to 0 when the system is restarted. |
| */ |
| public @IntRange(from = 0) int getConfigVersion() { |
| return mConfigVersion; |
| } |
| |
| /** |
| * Returns the ordered list of families included in the system fonts. |
| * @deprecated Use getFontFamilies instead. |
| * @hide |
| */ |
| @Deprecated |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public @NonNull FontFamily[] getFamilies() { |
| return mFamilies.toArray(new FontFamily[0]); |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeParcelableList(mFamilies, flags); |
| dest.writeParcelableList(mAliases, flags); |
| dest.writeLong(mLastModifiedTimeMillis); |
| dest.writeInt(mConfigVersion); |
| } |
| |
| public static final @NonNull Creator<FontConfig> CREATOR = new Creator<FontConfig>() { |
| @Override |
| public FontConfig createFromParcel(Parcel source) { |
| List<FontFamily> families = source.readParcelableList(new ArrayList<>(), |
| FontFamily.class.getClassLoader()); |
| List<Alias> aliases = source.readParcelableList(new ArrayList<>(), |
| Alias.class.getClassLoader()); |
| long lastModifiedDate = source.readLong(); |
| int configVersion = source.readInt(); |
| return new FontConfig(families, aliases, lastModifiedDate, configVersion); |
| } |
| |
| @Override |
| public FontConfig[] newArray(int size) { |
| return new FontConfig[size]; |
| } |
| }; |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| FontConfig that = (FontConfig) o; |
| return mLastModifiedTimeMillis == that.mLastModifiedTimeMillis |
| && mConfigVersion == that.mConfigVersion |
| && Objects.equals(mFamilies, that.mFamilies) |
| && Objects.equals(mAliases, that.mAliases); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mFamilies, mAliases, mLastModifiedTimeMillis, mConfigVersion); |
| } |
| |
| @Override |
| public String toString() { |
| return "FontConfig{" |
| + "mFamilies=" + mFamilies |
| + ", mAliases=" + mAliases |
| + ", mLastModifiedTimeMillis=" + mLastModifiedTimeMillis |
| + ", mConfigVersion=" + mConfigVersion |
| + '}'; |
| } |
| |
| /** |
| * Represents single font entry in system font configuration. |
| * |
| * A font is the most primitive unit of drawing character shapes. A font in system configuration |
| * is always referring a single OpenType compliant regular file in the file system. |
| * |
| * @see android.graphics.fonts.Font |
| */ |
| public static final class Font implements Parcelable { |
| private final @NonNull File mFile; |
| private final @Nullable File mOriginalFile; |
| private final @NonNull String mPostScriptName; |
| private final @NonNull FontStyle mStyle; |
| private final @IntRange(from = 0) int mIndex; |
| private final @NonNull String mFontVariationSettings; |
| private final @Nullable String mFontFamilyName; |
| |
| /** |
| * Construct a Font instance. |
| * |
| * @hide Only system server can create this instance and passed via IPC. |
| */ |
| public Font(@NonNull File file, @Nullable File originalFile, @NonNull String postScriptName, |
| @NonNull FontStyle style, @IntRange(from = 0) int index, |
| @NonNull String fontVariationSettings, @Nullable String fontFamilyName) { |
| mFile = file; |
| mOriginalFile = originalFile; |
| mPostScriptName = postScriptName; |
| mStyle = style; |
| mIndex = index; |
| mFontVariationSettings = fontVariationSettings; |
| mFontFamilyName = fontFamilyName; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeString8(mFile.getAbsolutePath()); |
| dest.writeString8(mOriginalFile == null ? null : mOriginalFile.getAbsolutePath()); |
| dest.writeString8(mPostScriptName); |
| dest.writeInt(mStyle.getWeight()); |
| dest.writeInt(mStyle.getSlant()); |
| dest.writeInt(mIndex); |
| dest.writeString8(mFontVariationSettings); |
| dest.writeString8(mFontFamilyName); |
| } |
| |
| public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() { |
| |
| @Override |
| public Font createFromParcel(Parcel source) { |
| File path = new File(source.readString8()); |
| String originalPathStr = source.readString8(); |
| File originalPath = originalPathStr == null ? null : new File(originalPathStr); |
| String postScriptName = source.readString8(); |
| int weight = source.readInt(); |
| int slant = source.readInt(); |
| int index = source.readInt(); |
| String varSettings = source.readString8(); |
| String fallback = source.readString8(); |
| |
| return new Font(path, originalPath, postScriptName, new FontStyle(weight, slant), |
| index, varSettings, fallback); |
| } |
| |
| @Override |
| public Font[] newArray(int size) { |
| return new Font[size]; |
| } |
| }; |
| |
| /** |
| * Returns the font file. |
| */ |
| public @NonNull File getFile() { |
| return mFile; |
| } |
| |
| /** |
| * Returns the original font file in the system directory. |
| * |
| * If the font file is not updated, returns null. |
| * |
| * @return returns the original font file in the system if the font file is updated. Returns |
| * null if the font file is not updated. |
| * @hide |
| */ |
| public @Nullable File getOriginalFile() { |
| return mOriginalFile; |
| } |
| |
| /** |
| * Returns the font style. |
| */ |
| public @NonNull FontStyle getStyle() { |
| return mStyle; |
| } |
| |
| |
| /** |
| * Return a font variation settings. |
| */ |
| public @NonNull String getFontVariationSettings() { |
| return mFontVariationSettings; |
| } |
| |
| /** |
| * A {@link Font} can be configured to be in the {@code Fallback List} for a |
| * {@link FontFamily}. |
| * |
| * For example a serif Hebrew [Font] can be defined in the {@code Fallback List} for |
| * {@code "serif"} {@link FontFamily}. |
| * |
| * If the return value is not {@code null}, then the font will be used in the |
| * {@code Fallback List} of that {@link FontFamily}. |
| * |
| * If the return value is {@code null}, then the font will be used in {@code Fallback List} |
| * of all {@link FontFamily}s. |
| */ |
| public @Nullable String getFontFamilyName() { |
| return mFontFamilyName; |
| } |
| |
| /** |
| * Returns the index to be used to access this font when accessing a TTC file. |
| */ |
| public int getTtcIndex() { |
| return mIndex; |
| } |
| |
| /** |
| * Returns the PostScript name of this font. |
| */ |
| public @NonNull String getPostScriptName() { |
| return mPostScriptName; |
| } |
| |
| /** |
| * Returns the list of axes associated to this font. |
| * @deprecated Use getFontVariationSettings |
| * @hide |
| */ |
| @Deprecated |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public @NonNull FontVariationAxis[] getAxes() { |
| return FontVariationAxis.fromFontVariationSettings(mFontVariationSettings); |
| } |
| |
| /** |
| * Returns the weight value for this font. |
| * @deprecated Use getStyle instead. |
| * @hide |
| */ |
| @Deprecated |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public int getWeight() { |
| return getStyle().getWeight(); |
| } |
| |
| /** |
| * Returns whether this font is italic. |
| * @deprecated Use getStyle instead. |
| * @hide |
| */ |
| @Deprecated |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public boolean isItalic() { |
| return getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| Font font = (Font) o; |
| return mIndex == font.mIndex |
| && Objects.equals(mFile, font.mFile) |
| && Objects.equals(mOriginalFile, font.mOriginalFile) |
| && Objects.equals(mStyle, font.mStyle) |
| && Objects.equals(mFontVariationSettings, font.mFontVariationSettings) |
| && Objects.equals(mFontFamilyName, font.mFontFamilyName); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mFile, mOriginalFile, mStyle, mIndex, mFontVariationSettings, |
| mFontFamilyName); |
| } |
| |
| @Override |
| public String toString() { |
| return "Font{" |
| + "mFile=" + mFile |
| + ", mOriginalFile=" + mOriginalFile |
| + ", mStyle=" + mStyle |
| + ", mIndex=" + mIndex |
| + ", mFontVariationSettings='" + mFontVariationSettings + '\'' |
| + ", mFontFamilyName='" + mFontFamilyName + '\'' |
| + '}'; |
| } |
| } |
| |
| /** |
| * Alias provides an alternative name for an existing font family. |
| * |
| * In the system font configuration, a font family can be an alias of another font family with |
| * different font weight. For example, "sans-serif-medium" can be a medium weight of |
| * "sans-serif" font family. In this example, {@link #getName()} returns "sans-serif-medium" and |
| * {@link #getOriginal()} return "sans-serif". The font family that doesn't have name can not be |
| * an original of the alias. |
| */ |
| public static final class Alias implements Parcelable { |
| private final @NonNull String mName; |
| private final @NonNull String mOriginal; |
| private final @IntRange(from = 0, to = 1000) int mWeight; |
| |
| /** |
| * Construct an alias instance. |
| * |
| * @param name alias for the font family. |
| * @param original original font family name. |
| * @param weight font weight of the original font family. |
| * @hide Only system server can create this instance and passed via IPC. |
| */ |
| public Alias(@NonNull String name, @NonNull String original, |
| @IntRange(from = 0, to = 1000) int weight) { |
| mName = name; |
| mOriginal = original; |
| mWeight = weight; |
| } |
| |
| /** |
| * Alias for the font family |
| */ |
| public @NonNull String getName() { |
| return mName; |
| } |
| |
| /** |
| * The name of the original font family. |
| */ |
| public @NonNull String getOriginal() { |
| return mOriginal; |
| } |
| |
| /** |
| * A font weight of the referring font family. |
| * |
| * @return a font weight of the referring font family. |
| */ |
| public @IntRange(from = 0, to = 1000) int getWeight() { |
| return mWeight; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeString8(mName); |
| dest.writeString8(mOriginal); |
| dest.writeInt(mWeight); |
| } |
| |
| public static final @NonNull Creator<Alias> CREATOR = new Creator<Alias>() { |
| |
| @Override |
| public Alias createFromParcel(Parcel source) { |
| String alias = source.readString8(); |
| String referName = source.readString8(); |
| int weight = source.readInt(); |
| return new Alias(alias, referName, weight); |
| } |
| |
| @Override |
| public Alias[] newArray(int size) { |
| return new Alias[size]; |
| } |
| }; |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| Alias alias = (Alias) o; |
| return mWeight == alias.mWeight |
| && Objects.equals(mName, alias.mName) |
| && Objects.equals(mOriginal, alias.mOriginal); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mName, mOriginal, mWeight); |
| } |
| |
| @Override |
| public String toString() { |
| return "Alias{" |
| + "mName='" + mName + '\'' |
| + ", mOriginal='" + mOriginal + '\'' |
| + ", mWeight=" + mWeight |
| + '}'; |
| } |
| } |
| |
| /** |
| * Represents a font family in the system font configuration. |
| * |
| * A {@link FontFamily} is a list of {@link Font}s for drawing text in various styles such as |
| * weight, slant. |
| * |
| * For example, a {@link FontFamily} can include the regular and bold styles of a {@link Font}. |
| * |
| * @see android.graphics.fonts.FontFamily |
| */ |
| public static final class FontFamily implements Parcelable { |
| private final @NonNull List<Font> mFonts; |
| private final @Nullable String mName; |
| private final @NonNull LocaleList mLocaleList; |
| private final @Variant int mVariant; |
| |
| /** @hide */ |
| @Retention(SOURCE) |
| @IntDef(prefix = { "VARIANT_" }, value = { |
| VARIANT_DEFAULT, |
| VARIANT_COMPACT, |
| VARIANT_ELEGANT |
| }) |
| public @interface Variant {} |
| |
| /** |
| * Value for font variant. |
| * |
| * Indicates the font has no variant attribute. |
| */ |
| public static final int VARIANT_DEFAULT = 0; |
| |
| /** |
| * Value for font variant. |
| * |
| * Indicates the font is for compact variant. |
| * @see android.graphics.Paint#setElegantTextHeight |
| */ |
| public static final int VARIANT_COMPACT = 1; |
| |
| /** |
| * Value for font variant. |
| * |
| * Indicates the font is for elegant variant. |
| * @see android.graphics.Paint#setElegantTextHeight |
| */ |
| public static final int VARIANT_ELEGANT = 2; |
| |
| /** |
| * Construct a family instance. |
| * |
| * @hide Only system server can create this instance and passed via IPC. |
| */ |
| public FontFamily(@NonNull List<Font> fonts, @Nullable String name, |
| @NonNull LocaleList localeList, @Variant int variant) { |
| mFonts = fonts; |
| mName = name; |
| mLocaleList = localeList; |
| mVariant = variant; |
| } |
| |
| /** |
| * Returns the list of {@link Font}s in this {@link FontFamily}. |
| * |
| * @return a list of font files. |
| */ |
| public @NonNull List<Font> getFontList() { |
| return mFonts; |
| } |
| |
| /** |
| * Returns the name of the {@link FontFamily}. |
| * |
| * When the name of a {@link FontFamily} is not null, this name is used to create a new |
| * {@code Fallback List}, and that {@code Fallback List}. Fallback List is the |
| * main building block for a {@link android.graphics.Typeface}. |
| * |
| * For example, if the {@link FontFamily} has the name "serif", then the system will create |
| * a “serif” {@code Fallback List} and it can be used by creating a Typeface via |
| * {@code Typeface.create("serif", Typeface.NORMAL);} |
| * |
| * When the name of a {@link FontFamily} is null, it will be appended to all of the |
| * {@code Fallback List}s. |
| */ |
| public @Nullable String getName() { |
| return mName; |
| } |
| |
| /** |
| * Returns the locale list if available. |
| * |
| * The locale list will be used for deciding which font family should be used in fallback |
| * list. |
| */ |
| public @NonNull LocaleList getLocaleList() { |
| return mLocaleList; |
| } |
| |
| /** |
| * Returns the text height variant. |
| */ |
| public @Variant int getVariant() { |
| return mVariant; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeParcelableList(mFonts, flags); |
| dest.writeString8(mName); |
| dest.writeString8(mLocaleList.toLanguageTags()); |
| dest.writeInt(mVariant); |
| } |
| |
| public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() { |
| |
| @Override |
| public FontFamily createFromParcel(Parcel source) { |
| List<Font> fonts = source.readParcelableList( |
| new ArrayList<>(), Font.class.getClassLoader()); |
| String name = source.readString8(); |
| String langTags = source.readString8(); |
| int variant = source.readInt(); |
| |
| return new FontFamily(fonts, name, LocaleList.forLanguageTags(langTags), variant); |
| } |
| |
| @Override |
| public FontFamily[] newArray(int size) { |
| return new FontFamily[size]; |
| } |
| }; |
| |
| /** |
| * Returns the list of fonts included in this family. |
| * @deprecated Use getFontList instead |
| * @hide |
| */ |
| @Deprecated |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public @Nullable Font[] getFonts() { |
| return mFonts.toArray(new Font[0]); |
| } |
| |
| /** |
| * Returns the comma separated BCP47 compliant languages for this family. May be null. |
| * @deprecated Use getLocaleList instead |
| * @hide |
| */ |
| @Deprecated |
| public @NonNull String getLanguages() { |
| return mLocaleList.toLanguageTags(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| FontFamily that = (FontFamily) o; |
| return mVariant == that.mVariant |
| && Objects.equals(mFonts, that.mFonts) |
| && Objects.equals(mName, that.mName) |
| && Objects.equals(mLocaleList, that.mLocaleList); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mFonts, mName, mLocaleList, mVariant); |
| } |
| |
| @Override |
| public String toString() { |
| return "FontFamily{" |
| + "mFonts=" + mFonts |
| + ", mName='" + mName + '\'' |
| + ", mLocaleList=" + mLocaleList |
| + ", mVariant=" + mVariant |
| + '}'; |
| } |
| } |
| } |