29
29
import android .annotation .UiThread ;
30
30
import android .compat .annotation .UnsupportedAppUsage ;
31
31
import android .content .res .AssetManager ;
32
+ import android .content .res .Resources ;
32
33
import android .graphics .fonts .Font ;
33
34
import android .graphics .fonts .FontFamily ;
34
35
import android .graphics .fonts .FontStyle ;
70
71
import java .io .InputStream ;
71
72
import java .lang .annotation .Retention ;
72
73
import java .lang .annotation .RetentionPolicy ;
74
+ import java .lang .reflect .Field ;
73
75
import java .nio .ByteBuffer ;
74
76
import java .nio .ByteOrder ;
75
77
import java .util .ArrayList ;
76
78
import java .util .Arrays ;
77
79
import java .util .Collections ;
78
80
import java .util .Comparator ;
81
+ import java .util .HashMap ;
79
82
import java .util .List ;
80
83
import java .util .Map ;
81
84
import java .util .Objects ;
@@ -145,6 +148,9 @@ public class Typeface {
145
148
private static final LruCache <String , Typeface > sDynamicTypefaceCache = new LruCache <>(16 );
146
149
private static final Object sDynamicCacheLock = new Object ();
147
150
151
+ // For dynamic default font styles
152
+ private static final HashMap <String , Typeface > sSystemFontOverrides = new HashMap <>();
153
+
148
154
private static final LruCache <Long , LruCache <String , Typeface >> sVariableCache =
149
155
new LruCache <>(16 );
150
156
private static final Object sVariableCacheLock = new Object ();
@@ -929,7 +935,7 @@ public CustomFallbackBuilder(@NonNull FontFamily family) {
929
935
* @return The best matching typeface.
930
936
*/
931
937
public static Typeface create (String familyName , @ Style int style ) {
932
- return create (getSystemDefaultTypeface (familyName ), style );
938
+ return create (getSystemOverrideTypeface (familyName ), style );
933
939
}
934
940
935
941
/**
@@ -1296,6 +1302,11 @@ public void releaseNativeObjectForTest() {
1296
1302
mCleaner .run ();
1297
1303
}
1298
1304
1305
+ private static Typeface getSystemOverrideTypeface (@ NonNull String familyName ) {
1306
+ Typeface tf = sSystemFontOverrides .get (familyName );
1307
+ return tf == null ? getSystemDefaultTypeface (familyName ) : tf ;
1308
+ }
1309
+
1299
1310
private static Typeface getSystemDefaultTypeface (@ NonNull String familyName ) {
1300
1311
Typeface tf = sSystemFontMap .get (familyName );
1301
1312
return tf == null ? Typeface .DEFAULT : tf ;
@@ -1477,6 +1488,60 @@ public static void setSystemFontMap(@Nullable SharedMemory sharedMemory)
1477
1488
}
1478
1489
}
1479
1490
1491
+ private static void setPublicDefaults (String familyName ) {
1492
+ synchronized (SYSTEM_FONT_MAP_LOCK ) {
1493
+ sDefaults = new Typeface [] {
1494
+ DEFAULT ,
1495
+ DEFAULT_BOLD ,
1496
+ create (getSystemDefaultTypeface (familyName ), Typeface .ITALIC ),
1497
+ create (getSystemDefaultTypeface (familyName ), Typeface .BOLD_ITALIC ),
1498
+ };
1499
+ }
1500
+ }
1501
+
1502
+ private static void setFinalField (String fieldName , Typeface value ) {
1503
+ synchronized (SYSTEM_FONT_MAP_LOCK ) {
1504
+ try {
1505
+ Field field = Typeface .class .getDeclaredField (fieldName );
1506
+ // isAccessible bypasses final on ART
1507
+ field .setAccessible (true );
1508
+ field .set (null , value );
1509
+ field .setAccessible (false );
1510
+ } catch (NoSuchFieldException | IllegalAccessException e ) {
1511
+ Log .e (TAG , "Failed to set Typeface." + fieldName , e );
1512
+ }
1513
+ }
1514
+ }
1515
+
1516
+ /** @hide */
1517
+ public static void updateDefaultFont (Resources res ) {
1518
+ synchronized (SYSTEM_FONT_MAP_LOCK ) {
1519
+ String familyName = res .getString (com .android .internal .R .string .config_bodyFontFamily );
1520
+ Typeface typeface = sSystemFontMap .get (familyName );
1521
+ if (typeface == null ) {
1522
+ // This should never happen, but if the system font family name is invalid, just return
1523
+ // instead of crashing the app.
1524
+ return ;
1525
+ }
1526
+
1527
+ setDefault (typeface );
1528
+
1529
+ // Static typefaces in public API
1530
+ setFinalField ("DEFAULT" , create (getSystemDefaultTypeface (familyName ), 0 ));
1531
+ setFinalField ("DEFAULT_BOLD" , create (getSystemDefaultTypeface (familyName ), Typeface .BOLD ));
1532
+ setFinalField ("SANS_SERIF" , DEFAULT );
1533
+
1534
+ // For default aliases used in framework styles
1535
+ sSystemFontOverrides .put ("sans-serif" , typeface );
1536
+ sSystemFontOverrides .put ("sans-serif-thin" , create (typeface , 100 , false ));
1537
+ sSystemFontOverrides .put ("sans-serif-light" , create (typeface , 300 , false ));
1538
+ sSystemFontOverrides .put ("sans-serif-medium" , create (typeface , 500 , false ));
1539
+ sSystemFontOverrides .put ("sans-serif-black" , create (typeface , 900 , false ));
1540
+
1541
+ setPublicDefaults (familyName );
1542
+ }
1543
+ }
1544
+
1480
1545
/** @hide */
1481
1546
@ VisibleForTesting
1482
1547
public static void setSystemFontMap (Map <String , Typeface > systemFontMap ) {
@@ -1497,12 +1562,7 @@ public static void setSystemFontMap(Map<String, Typeface> systemFontMap) {
1497
1562
nativeForceSetStaticFinalField ("SERIF" , create ("serif" , 0 ));
1498
1563
nativeForceSetStaticFinalField ("MONOSPACE" , create ("monospace" , 0 ));
1499
1564
1500
- sDefaults = new Typeface []{
1501
- DEFAULT ,
1502
- DEFAULT_BOLD ,
1503
- create ((String ) null , Typeface .ITALIC ),
1504
- create ((String ) null , Typeface .BOLD_ITALIC ),
1505
- };
1565
+ setPublicDefaults (null );
1506
1566
1507
1567
// A list of generic families to be registered in native.
1508
1568
// https://www.w3.org/TR/css-fonts-4/#generic-font-families
0 commit comments