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