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