/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package androidx.core.graphics; import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; import android.content.Context; import android.content.res.Resources; import android.graphics.Typeface; import android.os.Build; import android.os.CancellationSignal; import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RestrictTo; import androidx.collection.LruCache; import androidx.core.content.res.FontResourcesParserCompat; import androidx.core.content.res.FontResourcesParserCompat.FamilyResourceEntry; import androidx.core.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry; import androidx.core.content.res.FontResourcesParserCompat.ProviderResourceEntry; import androidx.core.content.res.ResourcesCompat; import androidx.core.os.BuildCompat; import androidx.core.provider.FontsContractCompat; import androidx.core.provider.FontsContractCompat.FontInfo; /** * Helper for accessing features in {@link Typeface}. * @hide */ @RestrictTo(LIBRARY_GROUP) public class TypefaceCompat { private static final String TAG = "TypefaceCompat"; private static final TypefaceCompatBaseImpl sTypefaceCompatImpl; static { if (BuildCompat.isAtLeastP()) { sTypefaceCompatImpl = new TypefaceCompatApi28Impl(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { sTypefaceCompatImpl = new TypefaceCompatApi26Impl(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && TypefaceCompatApi24Impl.isUsable()) { sTypefaceCompatImpl = new TypefaceCompatApi24Impl(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { sTypefaceCompatImpl = new TypefaceCompatApi21Impl(); } else { sTypefaceCompatImpl = new TypefaceCompatBaseImpl(); } } /** * Cache for Typeface objects dynamically loaded from assets. */ private static final LruCache sTypefaceCache = new LruCache<>(16); private TypefaceCompat() {} /** * Find from internal cache. * * @return null if not found. */ @Nullable public static Typeface findFromCache(@NonNull Resources resources, int id, int style) { return sTypefaceCache.get(createResourceUid(resources, id, style)); } /** * Create a unique id for a given Resource and id. * * @param resources Resources instance * @param id a resource id * @param style style to be used for this resource, -1 if not available. * @return Unique id for a given resource and id. */ private static String createResourceUid(final Resources resources, int id, int style) { return resources.getResourcePackageName(id) + "-" + id + "-" + style; } /** * Create Typeface from XML resource which root node is font-family. * * @return null if failed to create. */ @Nullable public static Typeface createFromResourcesFamilyXml( @NonNull Context context, @NonNull FamilyResourceEntry entry, @NonNull Resources resources, int id, int style, @Nullable ResourcesCompat.FontCallback fontCallback, @Nullable Handler handler, boolean isRequestFromLayoutInflator) { Typeface typeface; if (entry instanceof ProviderResourceEntry) { ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry; final boolean isBlocking = isRequestFromLayoutInflator ? providerEntry.getFetchStrategy() == FontResourcesParserCompat.FETCH_STRATEGY_BLOCKING : fontCallback == null; final int timeout = isRequestFromLayoutInflator ? providerEntry.getTimeout() : FontResourcesParserCompat.INFINITE_TIMEOUT_VALUE; typeface = FontsContractCompat.getFontSync(context, providerEntry.getRequest(), fontCallback, handler, isBlocking, timeout, style); } else { typeface = sTypefaceCompatImpl.createFromFontFamilyFilesResourceEntry( context, (FontFamilyFilesResourceEntry) entry, resources, style); if (fontCallback != null) { if (typeface != null) { fontCallback.callbackSuccessAsync(typeface, handler); } else { fontCallback.callbackFailAsync( FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR, handler); } } } if (typeface != null) { sTypefaceCache.put(createResourceUid(resources, id, style), typeface); } return typeface; } /** * Used by Resources to load a font resource of type font file. */ @Nullable public static Typeface createFromResourcesFontFile( @NonNull Context context, @NonNull Resources resources, int id, String path, int style) { Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile( context, resources, id, path, style); if (typeface != null) { final String resourceUid = createResourceUid(resources, id, style); sTypefaceCache.put(resourceUid, typeface); } return typeface; } /** * Create a Typeface from a given FontInfo list and a map that matches them to ByteBuffers. */ @Nullable public static Typeface createFromFontInfo(@NonNull Context context, @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) { return sTypefaceCompatImpl.createFromFontInfo(context, cancellationSignal, fonts, style); } }