blob: 2f7fb2f0ab9d129528a8ff2d9d7d6b03ee5c1cb7 [file] [log] [blame]
/*
* 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
+ '}';
}
}
}