• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.text;
18 
19 import static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.annotation.CurrentTimeMillisLong;
22 import android.annotation.IntDef;
23 import android.annotation.IntRange;
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.annotation.SystemApi;
27 import android.annotation.TestApi;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.graphics.fonts.FontStyle;
30 import android.graphics.fonts.FontVariationAxis;
31 import android.icu.util.ULocale;
32 import android.os.Build;
33 import android.os.LocaleList;
34 import android.os.Parcel;
35 import android.os.Parcelable;
36 
37 import java.io.File;
38 import java.lang.annotation.Retention;
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Objects;
44 
45 
46 /**
47  * Font configuration descriptions for System fonts.
48  *
49  * FontConfig represents the configuration for the fonts installed on the system. It is made of list
50  * of font families and aliases.
51  *
52  * @see FontFamily
53  * @see Alias
54  * @hide
55  */
56 @SystemApi
57 @TestApi
58 @android.ravenwood.annotation.RavenwoodKeepWholeClass
59 public final class FontConfig implements Parcelable {
60     private final @NonNull List<FontFamily> mFamilies;
61     private final @NonNull List<Alias> mAliases;
62     private final @NonNull List<NamedFamilyList> mNamedFamilyLists;
63     private final @NonNull List<Customization.LocaleFallback> mLocaleFallbackCustomizations;
64     private final long mLastModifiedTimeMillis;
65     private final int mConfigVersion;
66 
67     /**
68      * Construct a FontConfig instance.
69      *
70      * @param families a list of font families.
71      * @param aliases a list of aliases.
72      *
73      * @hide Only system server can create this instance and passed via IPC.
74      */
FontConfig(@onNull List<FontFamily> families, @NonNull List<Alias> aliases, @NonNull List<NamedFamilyList> namedFamilyLists, @NonNull List<Customization.LocaleFallback> localeFallbackCustomizations, long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion)75     public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases,
76             @NonNull List<NamedFamilyList> namedFamilyLists,
77             @NonNull List<Customization.LocaleFallback> localeFallbackCustomizations,
78             long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion) {
79         mFamilies = families;
80         mAliases = aliases;
81         mNamedFamilyLists = namedFamilyLists;
82         mLocaleFallbackCustomizations = localeFallbackCustomizations;
83         mLastModifiedTimeMillis = lastModifiedTimeMillis;
84         mConfigVersion = configVersion;
85     }
86 
87     /**
88      * @hide Keep this constructor for reoborectric.
89      */
FontConfig(@onNull List<FontFamily> families, @NonNull List<Alias> aliases, long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion)90     public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases,
91             long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion) {
92         this(families, aliases, Collections.emptyList(), Collections.emptyList(),
93                 lastModifiedTimeMillis, configVersion);
94     }
95 
96 
97     /**
98      * Returns the ordered list of font families available in the system.
99      *
100      * @return a list of font families.
101      * @see FontFamily
102      */
getFontFamilies()103     public @NonNull List<FontFamily> getFontFamilies() {
104         return mFamilies;
105     }
106 
107     /**
108      * Returns the list of aliases for mapping font families with other names.
109      *
110      * @return a list of font families.
111      * @see Alias
112      */
getAliases()113     public @NonNull List<Alias> getAliases() {
114         return mAliases;
115     }
116 
getNamedFamilyLists()117     public @NonNull List<NamedFamilyList> getNamedFamilyLists() {
118         return mNamedFamilyLists;
119     }
120 
121     /**
122      * Returns a locale fallback customizations.
123      *
124      * This field is used for creating the system fallback in the system server. This field is
125      * always empty in the application process.
126      *
127      * @hide
128      */
getLocaleFallbackCustomizations()129     public @NonNull List<Customization.LocaleFallback> getLocaleFallbackCustomizations() {
130         return mLocaleFallbackCustomizations;
131     }
132 
133     /**
134      * Returns the last modified time in milliseconds.
135      *
136      * This is a value of {@link System#currentTimeMillis()} when the system font configuration was
137      * modified last time.
138      *
139      * If there is no update, this return 0.
140      */
getLastModifiedTimeMillis()141     public @CurrentTimeMillisLong long getLastModifiedTimeMillis() {
142         return mLastModifiedTimeMillis;
143     }
144 
145     /**
146      * Returns the monotonically increasing config version value.
147      *
148      * The config version is reset to 0 when the system is restarted.
149      */
getConfigVersion()150     public @IntRange(from = 0) int getConfigVersion() {
151         return mConfigVersion;
152     }
153 
154     /**
155      * Returns the ordered list of families included in the system fonts.
156      * @deprecated Use getFontFamilies instead.
157      * @hide
158      */
159     @Deprecated
160     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getFamilies()161     public @NonNull FontFamily[] getFamilies() {
162         return mFamilies.toArray(new FontFamily[0]);
163     }
164 
165     @Override
describeContents()166     public int describeContents() {
167         return 0;
168     }
169 
170     @Override
writeToParcel(@onNull Parcel dest, int flags)171     public void writeToParcel(@NonNull Parcel dest, int flags) {
172         dest.writeTypedList(mFamilies, flags);
173         dest.writeTypedList(mAliases, flags);
174         dest.writeTypedList(mNamedFamilyLists, flags);
175         dest.writeLong(mLastModifiedTimeMillis);
176         dest.writeInt(mConfigVersion);
177     }
178 
179     public static final @NonNull Creator<FontConfig> CREATOR = new Creator<FontConfig>() {
180         @Override
181         public FontConfig createFromParcel(Parcel source) {
182             final List<FontFamily> families = new ArrayList<>();
183             source.readTypedList(families, FontFamily.CREATOR);
184             final List<Alias> aliases = new ArrayList<>();
185             source.readTypedList(aliases, Alias.CREATOR);
186             final List<NamedFamilyList> familyLists = new ArrayList<>();
187             source.readTypedList(familyLists, NamedFamilyList.CREATOR);
188             long lastModifiedDate = source.readLong();
189             int configVersion = source.readInt();
190             return new FontConfig(families, aliases, familyLists,
191                     Collections.emptyList(),  // Don't need to pass customization to API caller.
192                     lastModifiedDate, configVersion);
193         }
194 
195         @Override
196         public FontConfig[] newArray(int size) {
197             return new FontConfig[size];
198         }
199     };
200 
201     @Override
equals(Object o)202     public boolean equals(Object o) {
203         if (this == o) return true;
204         if (o == null || getClass() != o.getClass()) return false;
205         FontConfig that = (FontConfig) o;
206         return mLastModifiedTimeMillis == that.mLastModifiedTimeMillis
207                 && mConfigVersion == that.mConfigVersion
208                 && Objects.equals(mFamilies, that.mFamilies)
209                 && Objects.equals(mAliases, that.mAliases);
210     }
211 
212     @Override
hashCode()213     public int hashCode() {
214         return Objects.hash(mFamilies, mAliases, mLastModifiedTimeMillis, mConfigVersion);
215     }
216 
217     @Override
toString()218     public String toString() {
219         return "FontConfig{"
220                 + "mFamilies=" + mFamilies
221                 + ", mAliases=" + mAliases
222                 + ", mLastModifiedTimeMillis=" + mLastModifiedTimeMillis
223                 + ", mConfigVersion=" + mConfigVersion
224                 + '}';
225     }
226 
227     /**
228      * Represents single font entry in system font configuration.
229      *
230      * A font is the most primitive unit of drawing character shapes. A font in system configuration
231      * is always referring a single OpenType compliant regular file in the file system.
232      *
233      * @see android.graphics.fonts.Font
234      */
235     public static final class Font implements Parcelable {
236         private final @NonNull File mFile;
237         private final @Nullable File mOriginalFile;
238         private final @NonNull String mPostScriptName;
239         private final @NonNull FontStyle mStyle;
240         private final @IntRange(from = 0) int mIndex;
241         private final @NonNull String mFontVariationSettings;
242         private final @Nullable String mFontFamilyName;
243         private final @VarTypeAxes int mVarTypeAxes;
244 
245         /** @hide */
246         @Retention(SOURCE)
247         @IntDef(prefix = { "VAR_TYPE_AXES_" }, value = {
248                 VAR_TYPE_AXES_NONE,
249                 VAR_TYPE_AXES_WGHT,
250                 VAR_TYPE_AXES_ITAL,
251         })
252         public @interface VarTypeAxes {}
253 
254         /** @hide */
255         public static final int VAR_TYPE_AXES_NONE = 0;
256         /** @hide */
257         public static final int VAR_TYPE_AXES_WGHT = 1;
258         /** @hide */
259         public static final int VAR_TYPE_AXES_ITAL = 2;
260 
261         /**
262          * Construct a Font instance.
263          *
264          * @hide Only system server can create this instance and passed via IPC.
265          */
Font(@onNull File file, @Nullable File originalFile, @NonNull String postScriptName, @NonNull FontStyle style, @IntRange(from = 0) int index, @NonNull String fontVariationSettings, @Nullable String fontFamilyName, @VarTypeAxes int varTypeAxes)266         public Font(@NonNull File file, @Nullable File originalFile, @NonNull String postScriptName,
267                 @NonNull FontStyle style, @IntRange(from = 0) int index,
268                 @NonNull String fontVariationSettings, @Nullable String fontFamilyName,
269                 @VarTypeAxes int varTypeAxes) {
270             mFile = file;
271             mOriginalFile = originalFile;
272             mPostScriptName = postScriptName;
273             mStyle = style;
274             mIndex = index;
275             mFontVariationSettings = fontVariationSettings;
276             mFontFamilyName = fontFamilyName;
277             mVarTypeAxes = varTypeAxes;
278         }
279 
280         @Override
describeContents()281         public int describeContents() {
282             return 0;
283         }
284 
285         @Override
writeToParcel(@onNull Parcel dest, int flags)286         public void writeToParcel(@NonNull Parcel dest, int flags) {
287             dest.writeString8(mFile.getAbsolutePath());
288             dest.writeString8(mOriginalFile == null ? null : mOriginalFile.getAbsolutePath());
289             dest.writeString8(mPostScriptName);
290             dest.writeInt(mStyle.getWeight());
291             dest.writeInt(mStyle.getSlant());
292             dest.writeInt(mIndex);
293             dest.writeString8(mFontVariationSettings);
294             dest.writeString8(mFontFamilyName);
295             dest.writeInt(mVarTypeAxes);
296         }
297 
298         public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
299 
300             @Override
301             public Font createFromParcel(Parcel source) {
302                 File path = new File(source.readString8());
303                 String originalPathStr = source.readString8();
304                 File originalPath = originalPathStr == null ? null : new File(originalPathStr);
305                 String postScriptName = source.readString8();
306                 int weight = source.readInt();
307                 int slant = source.readInt();
308                 int index = source.readInt();
309                 String varSettings = source.readString8();
310                 String fallback = source.readString8();
311                 int varTypeAxes = source.readInt();
312 
313                 return new Font(path, originalPath, postScriptName, new FontStyle(weight, slant),
314                         index, varSettings, fallback, varTypeAxes);
315             }
316 
317             @Override
318             public Font[] newArray(int size) {
319                 return new Font[size];
320             }
321         };
322 
323         /**
324          * Returns the font file.
325          */
getFile()326         public @NonNull File getFile() {
327             return mFile;
328         }
329 
330         /**
331          * Returns the original font file in the system directory.
332          *
333          * If the font file is not updated, returns null.
334          *
335          * @return returns the original font file in the system if the font file is updated. Returns
336          *         null if the font file is not updated.
337          * @hide
338          */
getOriginalFile()339         public @Nullable File getOriginalFile() {
340             return mOriginalFile;
341         }
342 
343         /**
344          * Returns the font style.
345          */
getStyle()346         public @NonNull FontStyle getStyle() {
347             return mStyle;
348         }
349 
350 
351         /**
352          * Return a font variation settings.
353          */
getFontVariationSettings()354         public @NonNull String getFontVariationSettings() {
355             return mFontVariationSettings;
356         }
357 
358         /**
359          * A {@link Font} can be configured to be in the {@code Fallback List} for a
360          * {@link FontFamily}.
361          *
362          * For example a serif Hebrew [Font] can be defined in the {@code Fallback List} for
363          * {@code "serif"} {@link FontFamily}.
364          *
365          * If the return value is not {@code null}, then the font will be used in the
366          * {@code Fallback List} of that {@link FontFamily}.
367          *
368          * If the return value is {@code null}, then the font will be used in {@code Fallback List}
369          * of all {@link FontFamily}s.
370          */
getFontFamilyName()371         public @Nullable String getFontFamilyName() {
372             return mFontFamilyName;
373         }
374 
375         /**
376          * Returns the index to be used to access this font when accessing a TTC file.
377          */
getTtcIndex()378         public int getTtcIndex() {
379             return mIndex;
380         }
381 
382         /**
383          * Returns the PostScript name of this font.
384          */
getPostScriptName()385         public @NonNull String getPostScriptName() {
386             return mPostScriptName;
387         }
388 
389         /**
390          * Returns the list of supported axes tags for variable family type resolution.
391          *
392          * @hide
393          */
getVarTypeAxes()394         public @VarTypeAxes int getVarTypeAxes() {
395             return mVarTypeAxes;
396         }
397 
398         /**
399          * Returns the list of axes associated to this font.
400          * @deprecated Use getFontVariationSettings
401          * @hide
402          */
403         @Deprecated
404         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getAxes()405         public @NonNull FontVariationAxis[] getAxes() {
406             return FontVariationAxis.fromFontVariationSettings(mFontVariationSettings);
407         }
408 
409         /**
410          * Returns the weight value for this font.
411          * @deprecated Use getStyle instead.
412          * @hide
413          */
414         @Deprecated
415         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getWeight()416         public int getWeight() {
417             return getStyle().getWeight();
418         }
419 
420         /**
421          * Returns whether this font is italic.
422          * @deprecated Use getStyle instead.
423          * @hide
424          */
425         @Deprecated
426         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isItalic()427         public boolean isItalic() {
428             return getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC;
429         }
430 
431         @Override
equals(Object o)432         public boolean equals(Object o) {
433             if (this == o) return true;
434             if (o == null || getClass() != o.getClass()) return false;
435             Font font = (Font) o;
436             return mIndex == font.mIndex
437                     && Objects.equals(mFile, font.mFile)
438                     && Objects.equals(mOriginalFile, font.mOriginalFile)
439                     && Objects.equals(mStyle, font.mStyle)
440                     && Objects.equals(mFontVariationSettings, font.mFontVariationSettings)
441                     && Objects.equals(mFontFamilyName, font.mFontFamilyName)
442                     && mVarTypeAxes == font.mVarTypeAxes;
443         }
444 
445         @Override
hashCode()446         public int hashCode() {
447             return Objects.hash(mFile, mOriginalFile, mStyle, mIndex, mFontVariationSettings,
448                     mFontFamilyName, mVarTypeAxes);
449         }
450 
451         @Override
toString()452         public String toString() {
453             return "Font{"
454                     + "mFile=" + mFile
455                     + ", mOriginalFile=" + mOriginalFile
456                     + ", mStyle=" + mStyle
457                     + ", mIndex=" + mIndex
458                     + ", mFontVariationSettings='" + mFontVariationSettings + '\''
459                     + ", mFontFamilyName='" + mFontFamilyName + '\''
460                     + ", mVarTypeAxes='" + mVarTypeAxes + '\''
461                     + '}';
462         }
463     }
464 
465     /**
466      * Alias provides an alternative name for an existing font family.
467      *
468      * In the system font configuration, a font family can be an alias of another font family with
469      * different font weight. For example, "sans-serif-medium" can be a medium weight of
470      * "sans-serif" font family. In this example, {@link #getName()} returns "sans-serif-medium" and
471      * {@link #getOriginal()} return "sans-serif". The font family that doesn't have name can not be
472      * an original of the alias.
473      */
474     public static final class Alias implements Parcelable {
475         private final @NonNull String mName;
476         private final @NonNull String mOriginal;
477         private final @IntRange(from = 0, to = 1000) int mWeight;
478 
479         /**
480          * Construct an alias instance.
481          *
482          * @param name alias for the font family.
483          * @param original original font family name.
484          * @param weight font weight of the original font family.
485          * @hide Only system server can create this instance and passed via IPC.
486          */
Alias(@onNull String name, @NonNull String original, @IntRange(from = 0, to = 1000) int weight)487         public Alias(@NonNull String name, @NonNull String original,
488                 @IntRange(from = 0, to = 1000) int weight) {
489             mName = name;
490             mOriginal = original;
491             mWeight = weight;
492         }
493 
494         /**
495          * Alias for the font family
496          */
getName()497         public @NonNull String getName() {
498             return mName;
499         }
500 
501         /**
502          * The name of the original font family.
503          */
getOriginal()504         public @NonNull String getOriginal() {
505             return mOriginal;
506         }
507 
508         /**
509          * A font weight of the referring font family.
510          *
511          * @return a font weight of the referring font family.
512          */
getWeight()513         public @IntRange(from = 0, to = 1000) int getWeight() {
514             return mWeight;
515         }
516 
517         @Override
describeContents()518         public int describeContents() {
519             return 0;
520         }
521 
522         @Override
writeToParcel(@onNull Parcel dest, int flags)523         public void writeToParcel(@NonNull Parcel dest, int flags) {
524             dest.writeString8(mName);
525             dest.writeString8(mOriginal);
526             dest.writeInt(mWeight);
527         }
528 
529         public static final @NonNull Creator<Alias> CREATOR = new Creator<Alias>() {
530 
531             @Override
532             public Alias createFromParcel(Parcel source) {
533                 String alias = source.readString8();
534                 String referName = source.readString8();
535                 int weight = source.readInt();
536                 return new Alias(alias, referName, weight);
537             }
538 
539             @Override
540             public Alias[] newArray(int size) {
541                 return new Alias[size];
542             }
543         };
544 
545         @Override
equals(Object o)546         public boolean equals(Object o) {
547             if (this == o) return true;
548             if (o == null || getClass() != o.getClass()) return false;
549             Alias alias = (Alias) o;
550             return mWeight == alias.mWeight
551                     && Objects.equals(mName, alias.mName)
552                     && Objects.equals(mOriginal, alias.mOriginal);
553         }
554 
555         @Override
hashCode()556         public int hashCode() {
557             return Objects.hash(mName, mOriginal, mWeight);
558         }
559 
560         @Override
toString()561         public String toString() {
562             return "Alias{"
563                     + "mName='" + mName + '\''
564                     + ", mOriginal='" + mOriginal + '\''
565                     + ", mWeight=" + mWeight
566                     + '}';
567         }
568     }
569 
570     /**
571      * Represents a font family in the system font configuration.
572      *
573      * A {@link FontFamily} is a list of {@link Font}s for drawing text in various styles such as
574      * weight, slant.
575      *
576      * For example, a {@link FontFamily} can include the regular and bold styles of a {@link Font}.
577      *
578      * @see android.graphics.fonts.FontFamily
579      */
580     public static final class FontFamily implements Parcelable {
581         private final @NonNull List<Font> mFonts;
582         private final @NonNull LocaleList mLocaleList;
583         private final @Variant int mVariant;
584 
585         /** @hide */
586         @Retention(SOURCE)
587         @IntDef(prefix = { "VARIANT_" }, value = {
588                 VARIANT_DEFAULT,
589                 VARIANT_COMPACT,
590                 VARIANT_ELEGANT
591         })
592         public @interface Variant {}
593 
594         /**
595          * Value for font variant.
596          *
597          * Indicates the font has no variant attribute.
598          */
599         public static final int VARIANT_DEFAULT = 0;
600 
601         /**
602          * Value for font variant.
603          *
604          * Indicates the font is for compact variant.
605          * @see android.graphics.Paint#setElegantTextHeight
606          */
607         public static final int VARIANT_COMPACT = 1;
608 
609         /**
610          * Value for font variant.
611          *
612          * Indicates the font is for elegant variant.
613          * @see android.graphics.Paint#setElegantTextHeight
614          */
615         public static final int VARIANT_ELEGANT = 2;
616 
617         /**
618          * Construct a family instance.
619          *
620          * @hide Only system server can create this instance and passed via IPC.
621          */
FontFamily(@onNull List<Font> fonts, @NonNull LocaleList localeList, @Variant int variant)622         public FontFamily(@NonNull List<Font> fonts, @NonNull LocaleList localeList,
623                 @Variant int variant) {
624             mFonts = fonts;
625             mLocaleList = localeList;
626             mVariant = variant;
627         }
628 
629         /**
630          * Returns the list of {@link Font}s in this {@link FontFamily}.
631          *
632          * @return a list of font files.
633          */
getFontList()634         public @NonNull List<Font> getFontList() {
635             return mFonts;
636         }
637 
638         /**
639          * Returns the name of the {@link FontFamily}.
640          *
641          * When the name of a {@link FontFamily} is not null, this name is used to create a new
642          * {@code Fallback List}, and that {@code Fallback List}. Fallback List is the
643          * main building block for a {@link android.graphics.Typeface}.
644          *
645          * For example, if the {@link FontFamily} has the name "serif", then the system will create
646          * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
647          * {@code Typeface.create("serif", Typeface.NORMAL);}
648          *
649          * When the name of a {@link FontFamily} is null, it will be appended to all of the
650          * {@code Fallback List}s.
651          *
652          * @deprecated From API 34, this function always returns null. All font families which have
653          *             name attribute will be reported as a {@link NamedFamilyList}.
654          */
655         @Deprecated
getName()656         public @Nullable String getName() {
657             return null;
658         }
659 
660         /**
661          * Returns the locale list if available.
662          *
663          * The locale list will be used for deciding which font family should be used in fallback
664          * list.
665          */
getLocaleList()666         public @NonNull LocaleList getLocaleList() {
667             return mLocaleList;
668         }
669 
670         /**
671          * Returns the text height variant.
672          */
getVariant()673         public @Variant int getVariant() {
674             return mVariant;
675         }
676 
677         @Override
describeContents()678         public int describeContents() {
679             return 0;
680         }
681 
682         @Override
writeToParcel(@onNull Parcel dest, int flags)683         public void writeToParcel(@NonNull Parcel dest, int flags) {
684             dest.writeTypedList(mFonts, flags);
685             dest.writeString8(mLocaleList.toLanguageTags());
686             dest.writeInt(mVariant);
687         }
688 
689         public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() {
690 
691             @Override
692             public FontFamily createFromParcel(Parcel source) {
693                 List<Font> fonts = new ArrayList<>();
694                 source.readTypedList(fonts, Font.CREATOR);
695                 String langTags = source.readString8();
696                 int variant = source.readInt();
697 
698                 return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant);
699             }
700 
701             @Override
702             public FontFamily[] newArray(int size) {
703                 return new FontFamily[size];
704             }
705         };
706 
707         /**
708          * Returns the list of fonts included in this family.
709          * @deprecated Use getFontList instead
710          * @hide
711          */
712         @Deprecated
713         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getFonts()714         public @Nullable Font[] getFonts() {
715             return mFonts.toArray(new Font[0]);
716         }
717 
718         /**
719          * Returns the comma separated BCP47 compliant languages for this family. May be null.
720          * @deprecated Use getLocaleList instead
721          * @hide
722          */
723         @Deprecated
getLanguages()724         public @NonNull String getLanguages() {
725             return mLocaleList.toLanguageTags();
726         }
727 
728         @Override
equals(Object o)729         public boolean equals(Object o) {
730             if (this == o) return true;
731             if (o == null || getClass() != o.getClass()) return false;
732             FontFamily that = (FontFamily) o;
733             return mVariant == that.mVariant
734                     && Objects.equals(mFonts, that.mFonts)
735                     && Objects.equals(mLocaleList, that.mLocaleList);
736         }
737 
738         @Override
hashCode()739         public int hashCode() {
740             return Objects.hash(mFonts, mLocaleList, mVariant);
741         }
742 
743         @Override
toString()744         public String toString() {
745             return "FontFamily{"
746                     + "mFonts=" + mFonts
747                     + ", mLocaleList=" + mLocaleList
748                     + ", mVariant=" + mVariant
749                     + '}';
750         }
751     }
752 
753     /**
754      * Represents list of font family in the system font configuration.
755      *
756      * In the fonts_customization.xml, it can define the list of FontFamily as a named family. The
757      * list of FontFamily is treated as a fallback list when drawing.
758      *
759      * @see android.graphics.fonts.FontFamily
760      */
761     public static final class NamedFamilyList implements Parcelable {
762         private final List<FontFamily> mFamilies;
763         private final String mName;
764 
765         /** @hide */
NamedFamilyList(@onNull List<FontFamily> families, @NonNull String name)766         public NamedFamilyList(@NonNull List<FontFamily> families, @NonNull String name) {
767             mFamilies = families;
768             mName = name;
769         }
770 
771         /** @hide */
NamedFamilyList(@onNull FontFamily family)772         public NamedFamilyList(@NonNull FontFamily family) {
773             mFamilies = new ArrayList<>();
774             mFamilies.add(family);
775             mName = family.getName();
776         }
777 
778         /**
779          * A list of font families.
780          *
781          * @return a list of font families.
782          */
getFamilies()783         public @NonNull List<FontFamily> getFamilies() {
784             return mFamilies;
785         }
786 
787         /**
788          * Returns the name of the {@link FontFamily}.
789          *
790          * This name is used to create a new {@code Fallback List}.
791          *
792          * For example, if the {@link FontFamily} has the name "serif", then the system will create
793          * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
794          * {@code Typeface.create("serif", Typeface.NORMAL);}
795          */
getName()796         public @NonNull String getName() {
797             return mName;
798         }
799 
800         @Override
describeContents()801         public int describeContents() {
802             return 0;
803         }
804 
805         @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)806         public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
807             dest.writeTypedList(mFamilies, flags);
808             dest.writeString8(mName);
809         }
810 
811         public static final @NonNull Creator<NamedFamilyList> CREATOR = new Creator<>() {
812 
813             @Override
814             public NamedFamilyList createFromParcel(Parcel source) {
815                 final List<FontFamily> families = new ArrayList<>();
816                 source.readTypedList(families, FontFamily.CREATOR);
817                 String name = source.readString8();
818                 return new NamedFamilyList(families, name);
819             }
820 
821             @Override
822             public NamedFamilyList[] newArray(int size) {
823                 return new NamedFamilyList[size];
824             }
825         };
826 
827         @Override
equals(Object o)828         public boolean equals(Object o) {
829             if (this == o) return true;
830             if (o == null || getClass() != o.getClass()) return false;
831             NamedFamilyList that = (NamedFamilyList) o;
832             return Objects.equals(mFamilies, that.mFamilies) && Objects.equals(mName,
833                     that.mName);
834         }
835 
836         @Override
hashCode()837         public int hashCode() {
838             return Objects.hash(mFamilies, mName);
839         }
840 
841         @Override
toString()842         public String toString() {
843             return "NamedFamilyList{"
844                     + "mFamilies=" + mFamilies
845                     + ", mName='" + mName + '\''
846                     + '}';
847         }
848     }
849 
850     /** @hide */
851     public static class Customization {
Customization()852         private Customization() {}  // Singleton
853 
854         /**
855          * A class that represents customization of locale fallback
856          *
857          * This class represents a vendor customization of new-locale-family.
858          *
859          * <pre>
860          * <family customizationType="new-locale-family" operation="prepend" lang="ja-JP">
861          *     <font weight="400" style="normal">MyAlternativeFont.ttf
862          *         <axis tag="wght" stylevalue="400"/>
863          *     </font>
864          * </family>
865          * </pre>
866          *
867          * The operation can be one of prepend, replace or append. The operation prepend means that
868          * the new font family is inserted just before the original font family. The original font
869          * family is still in the fallback. The operation replace means that the original font
870          * family is replaced with new font family. The original font family is removed from the
871          * fallback. The operation append means that the new font family is inserted just after the
872          * original font family. The original font family is still in the fallback.
873          *
874          * The lang attribute is a BCP47 compliant language tag. The font fallback mainly uses ISO
875          * 15924 script code for matching. If the script code is missing, most likely script code
876          * will be used.
877          */
878         public static class LocaleFallback {
879             private final Locale mLocale;
880             private final int mOperation;
881             private final FontFamily mFamily;
882             private final String mScript;
883 
884             public static final int OPERATION_PREPEND = 0;
885             public static final int OPERATION_APPEND = 1;
886             public static final int OPERATION_REPLACE = 2;
887 
888             /** @hide */
889             @Retention(SOURCE)
890             @IntDef(prefix = { "OPERATION_" }, value = {
891                     OPERATION_PREPEND,
892                     OPERATION_APPEND,
893                     OPERATION_REPLACE
894             })
895             public @interface Operation {}
896 
897 
LocaleFallback(@onNull Locale locale, @Operation int operation, @NonNull FontFamily family)898             public LocaleFallback(@NonNull Locale locale, @Operation int operation,
899                     @NonNull FontFamily family) {
900                 mLocale = locale;
901                 mOperation = operation;
902                 mFamily = family;
903                 mScript = resolveScript(locale);
904             }
905 
906             /**
907              * A customization target locale.
908              * @return a locale
909              */
getLocale()910             public @NonNull Locale getLocale() {
911                 return mLocale;
912             }
913 
914             /**
915              * An operation to be applied to the original font family.
916              *
917              * The operation can be one of {@link #OPERATION_PREPEND}, {@link #OPERATION_REPLACE} or
918              * {@link #OPERATION_APPEND}.
919              *
920              * The operation prepend ({@link #OPERATION_PREPEND}) means that the new font family is
921              * inserted just before the original font family. The original font family is still in
922              * the fallback.
923              *
924              * The operation replace ({@link #OPERATION_REPLACE}) means that the original font
925              * family is replaced with new font family. The original font family is removed from the
926              * fallback.
927              *
928              * The operation append ({@link #OPERATION_APPEND}) means that the new font family is
929              * inserted just after the original font family. The original font family is still in
930              * the fallback.
931              *
932              * @return an operation.
933              */
getOperation()934             public @Operation int getOperation() {
935                 return mOperation;
936             }
937 
938             /**
939              * Returns a family to be inserted or replaced to the fallback.
940              *
941              * @return a family
942              */
getFamily()943             public @NonNull FontFamily getFamily() {
944                 return mFamily;
945             }
946 
947             /**
948              * Returns a script of the locale. If the script is missing in the given locale, the
949              * most likely locale is returned.
950              */
getScript()951             public @NonNull String getScript() {
952                 return mScript;
953             }
954 
955             @Override
toString()956             public String toString() {
957                 return "LocaleFallback{"
958                         + "mLocale=" + mLocale
959                         + ", mOperation=" + mOperation
960                         + ", mFamily=" + mFamily
961                         + '}';
962             }
963         }
964     }
965 
966     /** @hide */
resolveScript(Locale locale)967     public static String resolveScript(Locale locale) {
968         String script = locale.getScript();
969         if (script != null && !script.isEmpty()) {
970             return script;
971         }
972         return ULocale.addLikelySubtags(ULocale.forLocale(locale)).getScript();
973     }
974 }
975