/*
 * Copyright (C) 2006 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 android.graphics;

import static android.content.res.FontResourcesParser.FamilyResourceEntry;
import static android.content.res.FontResourcesParser.FontFamilyFilesResourceEntry;
import static android.content.res.FontResourcesParser.FontFileResourceEntry;
import static android.content.res.FontResourcesParser.ProviderResourceEntry;

import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontStyle;
import android.graphics.fonts.FontVariationAxis;
import android.graphics.fonts.SystemFonts;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.provider.FontRequest;
import android.provider.FontsContract;
import android.text.FontConfig;
import android.util.Base64;
import android.util.LongSparseArray;
import android.util.LruCache;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import dalvik.annotation.optimization.CriticalNative;

import libcore.util.NativeAllocationRegistry;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The Typeface class specifies the typeface and intrinsic style of a font.
 * This is used in the paint, along with optionally Paint settings like
 * textSize, textSkewX, textScaleX to specify
 * how text appears when drawn (and measured).
 */
public class Typeface {

    private static String TAG = "Typeface";

    private static final NativeAllocationRegistry sRegistry =
            NativeAllocationRegistry.createMalloced(
            Typeface.class.getClassLoader(), nativeGetReleaseFunc());

    /** The default NORMAL typeface object */
    public static final Typeface DEFAULT;
    /**
     * The default BOLD typeface object. Note: this may be not actually be
     * bold, depending on what fonts are installed. Call getStyle() to know
     * for sure.
     */
    public static final Typeface DEFAULT_BOLD;
    /** The NORMAL style of the default sans serif typeface. */
    public static final Typeface SANS_SERIF;
    /** The NORMAL style of the default serif typeface. */
    public static final Typeface SERIF;
    /** The NORMAL style of the default monospace typeface. */
    public static final Typeface MONOSPACE;

    /**
     * The default {@link Typeface}s for different text styles.
     * Call {@link #defaultFromStyle(int)} to get the default typeface for the given text style.
     * It shouldn't be changed for app wide typeface settings. Please use theme and font XML for
     * the same purpose.
     */
    @UnsupportedAppUsage(trackingBug = 123769446)
    static Typeface[] sDefaults;

    /**
     * Cache for Typeface objects for style variant. Currently max size is 3.
     */
    @GuardedBy("sStyledCacheLock")
    private static final LongSparseArray<SparseArray<Typeface>> sStyledTypefaceCache =
            new LongSparseArray<>(3);
    private static final Object sStyledCacheLock = new Object();

    /**
     * Cache for Typeface objects for weight variant. Currently max size is 3.
     */
    @GuardedBy("sWeightCacheLock")
    private static final LongSparseArray<SparseArray<Typeface>> sWeightTypefaceCache =
            new LongSparseArray<>(3);
    private static final Object sWeightCacheLock = new Object();

    /**
     * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
     */
    @GuardedBy("sDynamicCacheLock")
    private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
    private static final Object sDynamicCacheLock = new Object();

    static Typeface sDefaultTypeface;

    // Following two fields are not used but left for hiddenapi private list
    /**
     * sSystemFontMap is read only and unmodifiable.
     * Use public API {@link #create(String, int)} to get the typeface for given familyName.
     */
    @UnsupportedAppUsage(trackingBug = 123769347)
    static final Map<String, Typeface> sSystemFontMap;

    // We cannot support sSystemFallbackMap since we will migrate to public FontFamily API.
    /**
     * @deprecated Use {@link android.graphics.fonts.FontFamily} instead.
     */
    @UnsupportedAppUsage(trackingBug = 123768928)
    @Deprecated
    static final Map<String, android.graphics.FontFamily[]> sSystemFallbackMap =
            Collections.emptyMap();

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public long native_instance;

    /** @hide */
    @IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Style {}

    // Style
    public static final int NORMAL = 0;
    public static final int BOLD = 1;
    public static final int ITALIC = 2;
    public static final int BOLD_ITALIC = 3;
    /** @hide */ public static final int STYLE_MASK = 0x03;

    @UnsupportedAppUsage
    private @Style int mStyle = 0;

    private @IntRange(from = 0, to = FontStyle.FONT_WEIGHT_MAX) int mWeight = 0;

    // Value for weight and italic. Indicates the value is resolved by font metadata.
    // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
    /** @hide */
    public static final int RESOLVE_BY_FONT_TABLE = -1;
    private static final String DEFAULT_FAMILY = "sans-serif";

    // Style value for building typeface.
    private static final int STYLE_NORMAL = 0;
    private static final int STYLE_ITALIC = 1;

    private int[] mSupportedAxes;
    private static final int[] EMPTY_AXES = {};

    /**
     * Please use font in xml and also your application global theme to change the default Typeface.
     * android:textViewStyle and its attribute android:textAppearance can be used in order to change
     * typeface and other text related properties.
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    private static void setDefault(Typeface t) {
        sDefaultTypeface = t;
        nativeSetDefault(t.native_instance);
    }

    /** Returns the typeface's weight value */
    public @IntRange(from = 0, to = 1000) int getWeight() {
        return mWeight;
    }

    /** Returns the typeface's intrinsic style attributes */
    public @Style int getStyle() {
        return mStyle;
    }

    /** Returns true if getStyle() has the BOLD bit set. */
    public final boolean isBold() {
        return (mStyle & BOLD) != 0;
    }

    /** Returns true if getStyle() has the ITALIC bit set. */
    public final boolean isItalic() {
        return (mStyle & ITALIC) != 0;
    }

    /**
     * @hide
     * Used by Resources to load a font resource of type xml.
     */
    @Nullable
    public static Typeface createFromResources(
            FamilyResourceEntry entry, AssetManager mgr, String path) {
        if (entry instanceof ProviderResourceEntry) {
            final ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry;
            // Downloadable font
            List<List<String>> givenCerts = providerEntry.getCerts();
            List<List<byte[]>> certs = new ArrayList<>();
            if (givenCerts != null) {
                for (int i = 0; i < givenCerts.size(); i++) {
                    List<String> certSet = givenCerts.get(i);
                    List<byte[]> byteArraySet = new ArrayList<>();
                    for (int j = 0; j < certSet.size(); j++) {
                        byteArraySet.add(Base64.decode(certSet.get(j), Base64.DEFAULT));
                    }
                    certs.add(byteArraySet);
                }
            }
            // Downloaded font and it wasn't cached, request it again and return a
            // default font instead (nothing we can do now).
            FontRequest request = new FontRequest(providerEntry.getAuthority(),
                    providerEntry.getPackage(), providerEntry.getQuery(), certs);
            Typeface typeface = FontsContract.getFontSync(request);
            return typeface == null ? DEFAULT : typeface;
        }

        Typeface typeface = findFromCache(mgr, path);
        if (typeface != null) return typeface;

        // family is FontFamilyFilesResourceEntry
        final FontFamilyFilesResourceEntry filesEntry = (FontFamilyFilesResourceEntry) entry;

        try {
            FontFamily.Builder familyBuilder = null;
            for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) {
                final Font.Builder fontBuilder = new Font.Builder(mgr, fontFile.getFileName(),
                        false /* isAsset */, 0 /* cookie */)
                        .setTtcIndex(fontFile.getTtcIndex())
                        .setFontVariationSettings(fontFile.getVariationSettings());
                if (fontFile.getWeight() != Typeface.RESOLVE_BY_FONT_TABLE) {
                    fontBuilder.setWeight(fontFile.getWeight());
                }
                if (fontFile.getItalic() != Typeface.RESOLVE_BY_FONT_TABLE) {
                    fontBuilder.setSlant(fontFile.getItalic() == FontFileResourceEntry.ITALIC
                            ?  FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT);
                }

                if (familyBuilder == null) {
                    familyBuilder = new FontFamily.Builder(fontBuilder.build());
                } else {
                    familyBuilder.addFont(fontBuilder.build());
                }
            }
            if (familyBuilder == null) {
                return Typeface.DEFAULT;
            }
            final FontFamily family = familyBuilder.build();
            final FontStyle normal = new FontStyle(FontStyle.FONT_WEIGHT_NORMAL,
                    FontStyle.FONT_SLANT_UPRIGHT);
            Font bestFont = family.getFont(0);
            int bestScore = normal.getMatchScore(bestFont.getStyle());
            for (int i = 1; i < family.getSize(); ++i) {
                final Font candidate = family.getFont(i);
                final int score = normal.getMatchScore(candidate.getStyle());
                if (score < bestScore) {
                    bestFont = candidate;
                    bestScore = score;
                }
            }
            typeface = new Typeface.CustomFallbackBuilder(family)
                    .setStyle(bestFont.getStyle())
                    .build();
        } catch (IllegalArgumentException e) {
            // To be a compatible behavior with API28 or before, catch IllegalArgumentExcetpion
            // thrown by native code and returns null.
            return null;
        } catch (IOException e) {
            typeface = Typeface.DEFAULT;
        }
        synchronized (sDynamicCacheLock) {
            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
                    null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */,
                    RESOLVE_BY_FONT_TABLE /* italic */, DEFAULT_FAMILY);
            sDynamicTypefaceCache.put(key, typeface);
        }
        return typeface;
    }

    /**
     * Used by resources for cached loading if the font is available.
     * @hide
     */
    public static Typeface findFromCache(AssetManager mgr, String path) {
        synchronized (sDynamicCacheLock) {
            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */,
                    RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */,
                    DEFAULT_FAMILY);
            Typeface typeface = sDynamicTypefaceCache.get(key);
            if (typeface != null) {
                return typeface;
            }
        }
        return null;
    }

    /**
     * A builder class for creating new Typeface instance.
     *
     * <p>
     * Examples,
     * 1) Create Typeface from ttf file.
     * <pre>
     * <code>
     * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
     * Typeface typeface = builder.build();
     * </code>
     * </pre>
     *
     * 2) Create Typeface from ttc file in assets directory.
     * <pre>
     * <code>
     * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc");
     * builder.setTtcIndex(2);  // Set index of font collection.
     * Typeface typeface = builder.build();
     * </code>
     * </pre>
     *
     * 3) Create Typeface with variation settings.
     * <pre>
     * <code>
     * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
     * builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
     * builder.setWeight(700);  // Tell the system that this is a bold font.
     * builder.setItalic(true);  // Tell the system that this is an italic style font.
     * Typeface typeface = builder.build();
     * </code>
     * </pre>
     * </p>
     */
    public static final class Builder {
        /** @hide */
        public static final int NORMAL_WEIGHT = 400;
        /** @hide */
        public static final int BOLD_WEIGHT = 700;

        // Kept for generating asset cache key.
        private final AssetManager mAssetManager;
        private final String mPath;

        private final @Nullable Font.Builder mFontBuilder;

        private String mFallbackFamilyName;

        private int mWeight = RESOLVE_BY_FONT_TABLE;
        private int mItalic = RESOLVE_BY_FONT_TABLE;

        /**
         * Constructs a builder with a file path.
         *
         * @param path The file object refers to the font file.
         */
        public Builder(@NonNull File path) {
            mFontBuilder = new Font.Builder(path);
            mAssetManager = null;
            mPath = null;
        }

        /**
         * Constructs a builder with a file descriptor.
         *
         * Caller is responsible for closing the passed file descriptor after {@link #build} is
         * called.
         *
         * @param fd The file descriptor. The passed fd must be mmap-able.
         */
        public Builder(@NonNull FileDescriptor fd) {
            Font.Builder builder;
            try {
                builder = new Font.Builder(ParcelFileDescriptor.dup(fd));
            } catch (IOException e) {
                // We cannot tell the error to developer at this moment since we cannot change the
                // public API signature. Instead, silently fallbacks to system fallback in the build
                // method as the same as other error cases.
                builder = null;
            }
            mFontBuilder = builder;
            mAssetManager = null;
            mPath = null;
        }

        /**
         * Constructs a builder with a file path.
         *
         * @param path The full path to the font file.
         */
        public Builder(@NonNull String path) {
            mFontBuilder = new Font.Builder(new File(path));
            mAssetManager = null;
            mPath = null;
        }

        /**
         * Constructs a builder from an asset manager and a file path in an asset directory.
         *
         * @param assetManager The application's asset manager
         * @param path The file name of the font data in the asset directory
         */
        public Builder(@NonNull AssetManager assetManager, @NonNull String path) {
            this(assetManager, path, true /* is asset */, 0 /* cookie */);
        }

        /**
         * Constructs a builder from an asset manager and a file path in an asset directory.
         *
         * @param assetManager The application's asset manager
         * @param path The file name of the font data in the asset directory
         * @param cookie a cookie for the asset
         * @hide
         */
        public Builder(@NonNull AssetManager assetManager, @NonNull String path, boolean isAsset,
                int cookie) {
            mFontBuilder = new Font.Builder(assetManager, path, isAsset, cookie);
            mAssetManager = assetManager;
            mPath = path;
        }

        /**
         * Sets weight of the font.
         *
         * Tells the system the weight of the given font. If not provided, the system will resolve
         * the weight value by reading font tables.
         * @param weight a weight value.
         */
        public Builder setWeight(@IntRange(from = 1, to = 1000) int weight) {
            mWeight = weight;
            mFontBuilder.setWeight(weight);
            return this;
        }

        /**
         * Sets italic information of the font.
         *
         * Tells the system the style of the given font. If not provided, the system will resolve
         * the style by reading font tables.
         * @param italic {@code true} if the font is italic. Otherwise {@code false}.
         */
        public Builder setItalic(boolean italic) {
            mItalic = italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT;
            mFontBuilder.setSlant(mItalic);
            return this;
        }

        /**
         * Sets an index of the font collection. See {@link android.R.attr#ttcIndex}.
         *
         * Can not be used for Typeface source. build() method will return null for invalid index.
         * @param ttcIndex An index of the font collection. If the font source is not font
         *                 collection, do not call this method or specify 0.
         */
        public Builder setTtcIndex(@IntRange(from = 0) int ttcIndex) {
            mFontBuilder.setTtcIndex(ttcIndex);
            return this;
        }

        /**
         * Sets a font variation settings.
         *
         * @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}.
         * @throws IllegalArgumentException If given string is not a valid font variation settings
         *                                  format.
         */
        public Builder setFontVariationSettings(@Nullable String variationSettings) {
            mFontBuilder.setFontVariationSettings(variationSettings);
            return this;
        }

        /**
         * Sets a font variation settings.
         *
         * @param axes An array of font variation axis tag-value pairs.
         */
        public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
            mFontBuilder.setFontVariationSettings(axes);
            return this;
        }

        /**
         * Sets a fallback family name.
         *
         * By specifying a fallback family name, a fallback Typeface will be returned if the
         * {@link #build} method fails to create a Typeface from the provided font. The fallback
         * family will be resolved with the provided weight and italic information specified by
         * {@link #setWeight} and {@link #setItalic}.
         *
         * If {@link #setWeight} is not called, the fallback family keeps the default weight.
         * Similary, if {@link #setItalic} is not called, the fallback family keeps the default
         * italic information. For example, calling {@code builder.setFallback("sans-serif-light")}
         * is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in
         * terms of fallback. The default weight and italic information are overridden by calling
         * {@link #setWeight} and {@link #setItalic}. For example, if a Typeface is constructed
         * using {@code builder.setFallback("sans-serif-light").setWeight(700)}, the fallback text
         * will render as sans serif bold.
         *
         * @param familyName A family name to be used for fallback if the provided font can not be
         *                   used. By passing {@code null}, build() returns {@code null}.
         *                   If {@link #setFallback} is not called on the builder, {@code null}
         *                   is assumed.
         */
        public Builder setFallback(@Nullable String familyName) {
            mFallbackFamilyName = familyName;
            return this;
        }

        /**
         * Creates a unique id for a given AssetManager and asset path.
         *
         * @param mgr  AssetManager instance
         * @param path The path for the asset.
         * @param ttcIndex The TTC index for the font.
         * @param axes The font variation settings.
         * @return Unique id for a given AssetManager and asset path.
         */
        private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
                @Nullable FontVariationAxis[] axes, int weight, int italic, String fallback) {
            final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
            final StringBuilder builder = new StringBuilder();
            final int size = pkgs.size();
            for (int i = 0; i < size; i++) {
                builder.append(pkgs.valueAt(i));
                builder.append("-");
            }
            builder.append(path);
            builder.append("-");
            builder.append(Integer.toString(ttcIndex));
            builder.append("-");
            builder.append(Integer.toString(weight));
            builder.append("-");
            builder.append(Integer.toString(italic));
            // Family name may contain hyphen. Use double hyphen for avoiding key conflicts before
            // and after appending falblack name.
            builder.append("--");
            builder.append(fallback);
            builder.append("--");
            if (axes != null) {
                for (FontVariationAxis axis : axes) {
                    builder.append(axis.getTag());
                    builder.append("-");
                    builder.append(Float.toString(axis.getStyleValue()));
                }
            }
            return builder.toString();
        }

        private Typeface resolveFallbackTypeface() {
            if (mFallbackFamilyName == null) {
                return null;
            }

            final Typeface base =  getSystemDefaultTypeface(mFallbackFamilyName);
            if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
                return base;
            }

            final int weight = (mWeight == RESOLVE_BY_FONT_TABLE) ? base.mWeight : mWeight;
            final boolean italic =
                    (mItalic == RESOLVE_BY_FONT_TABLE) ? (base.mStyle & ITALIC) != 0 : mItalic == 1;
            return createWeightStyle(base, weight, italic);
        }

        /**
         * Generates new Typeface from specified configuration.
         *
         * @return Newly created Typeface. May return null if some parameters are invalid.
         */
        public Typeface build() {
            if (mFontBuilder == null) {
                return resolveFallbackTypeface();
            }
            try {
                final Font font = mFontBuilder.build();
                final String key = mAssetManager == null ? null : createAssetUid(
                        mAssetManager, mPath, font.getTtcIndex(), font.getAxes(),
                        mWeight, mItalic,
                        mFallbackFamilyName == null ? DEFAULT_FAMILY : mFallbackFamilyName);
                if (key != null) {
                    // Dynamic cache lookup is only for assets.
                    synchronized (sDynamicCacheLock) {
                        final Typeface typeface = sDynamicTypefaceCache.get(key);
                        if (typeface != null) {
                            return typeface;
                        }
                    }
                }
                final FontFamily family = new FontFamily.Builder(font).build();
                final int weight = mWeight == RESOLVE_BY_FONT_TABLE
                        ? font.getStyle().getWeight() : mWeight;
                final int slant = mItalic == RESOLVE_BY_FONT_TABLE
                        ? font.getStyle().getSlant() : mItalic;
                final CustomFallbackBuilder builder = new CustomFallbackBuilder(family)
                        .setStyle(new FontStyle(weight, slant));
                if (mFallbackFamilyName != null) {
                    builder.setSystemFallback(mFallbackFamilyName);
                }
                final Typeface typeface = builder.build();
                if (key != null) {
                    synchronized (sDynamicCacheLock) {
                        sDynamicTypefaceCache.put(key, typeface);
                    }
                }
                return typeface;
            } catch (IOException | IllegalArgumentException e) {
                return resolveFallbackTypeface();
            }
        }
    }

    /**
     * A builder class for creating new Typeface instance.
     *
     * There are two font fallback mechanisms, custom font fallback and system font fallback.
     * The custom font fallback is a simple ordered list. The text renderer tries to see if it can
     * render a character with the first font and if that font does not support the character, try
     * next one and so on. It will keep trying until end of the custom fallback chain. The maximum
     * length of the custom fallback chain is 64.
     * The system font fallback is a system pre-defined fallback chain. The system fallback is
     * processed only when no matching font is found in the custom font fallback.
     *
     * <p>
     * Examples,
     * 1) Create Typeface from single ttf file.
     * <pre>
     * <code>
     * Font font = new Font.Builder("your_font_file.ttf").build();
     * FontFamily family = new FontFamily.Builder(font).build();
     * Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
     * </code>
     * </pre>
     *
     * 2) Create Typeface from multiple font files and select bold style by default.
     * <pre>
     * <code>
     * Font regularFont = new Font.Builder("regular.ttf").build();
     * Font boldFont = new Font.Builder("bold.ttf").build();
     * FontFamily family = new FontFamily.Builder(regularFont)
     *     .addFont(boldFont).build();
     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
     *     .setWeight(Font.FONT_WEIGHT_BOLD)  // Set bold style as the default style.
     *                                        // If the font family doesn't have bold style font,
     *                                        // system will select the closest font.
     *     .build();
     * </code>
     * </pre>
     *
     * 3) Create Typeface from single ttf file and if that font does not have glyph for the
     * characters, use "serif" font family instead.
     * <pre>
     * <code>
     * Font font = new Font.Builder("your_font_file.ttf").build();
     * FontFamily family = new FontFamily.Builder(font).build();
     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
     *     .setSystemFallback("serif")  // Set serif font family as the fallback.
     *     .build();
     * </code>
     * </pre>
     * 4) Create Typeface from single ttf file and set another ttf file for the fallback.
     * <pre>
     * <code>
     * Font font = new Font.Builder("English.ttf").build();
     * FontFamily family = new FontFamily.Builder(font).build();
     *
     * Font fallbackFont = new Font.Builder("Arabic.ttf").build();
     * FontFamily fallbackFamily = new FontFamily.Builder(fallbackFont).build();
     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
     *     .addCustomFallback(fallbackFamily)  // Specify fallback family.
     *     .setSystemFallback("serif")  // Set serif font family as the fallback.
     *     .build();
     * </code>
     * </pre>
     * </p>
     */
    public static final class CustomFallbackBuilder {
        private static final int MAX_CUSTOM_FALLBACK = 64;
        private final ArrayList<FontFamily> mFamilies = new ArrayList<>();
        private String mFallbackName = null;
        private @Nullable FontStyle mStyle;

        /**
         * Returns the maximum capacity of custom fallback families.
         *
         * This includes the the first font family passed to the constructor.
         * It is guaranteed that the value will be greater than or equal to 64.
         *
         * @return the maximum number of font families for the custom fallback
         */
        public static @IntRange(from = 64) int getMaxCustomFallbackCount() {
            return MAX_CUSTOM_FALLBACK;
        }

        /**
         * Constructs a builder with a font family.
         *
         * @param family a family object
         */
        public CustomFallbackBuilder(@NonNull FontFamily family) {
            Preconditions.checkNotNull(family);
            mFamilies.add(family);
        }

        /**
         * Sets a system fallback by name.
         *
         * You can specify generic font familiy names or OEM specific family names. If the system
         * don't have a specified fallback, the default fallback is used instead.
         * For more information about generic font families, see <a
         * href="https://www.w3.org/TR/css-fonts-4/#generic-font-families">CSS specification</a>
         *
         * For more information about fallback, see class description.
         *
         * @param familyName a family name to be used for fallback if the provided fonts can not be
         *                   used
         */
        public @NonNull CustomFallbackBuilder setSystemFallback(@NonNull String familyName) {
            Preconditions.checkNotNull(familyName);
            mFallbackName = familyName;
            return this;
        }

        /**
         * Sets a font style of the Typeface.
         *
         * If the font family doesn't have a font of given style, system will select the closest
         * font from font family. For example, if a font family has fonts of 300 weight and 700
         * weight then setWeight(400) is called, system will select the font of 300 weight.
         *
         * @param style a font style
         */
        public @NonNull CustomFallbackBuilder setStyle(@NonNull FontStyle style) {
            mStyle = style;
            return this;
        }

        /**
         * Append a font family to the end of the custom font fallback.
         *
         * You can set up to 64 custom fallback families including the first font family you passed
         * to the constructor.
         * For more information about fallback, see class description.
         *
         * @param family a fallback family
         * @throws IllegalArgumentException if you give more than 64 custom fallback families
         */
        public @NonNull CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
            Preconditions.checkNotNull(family);
            Preconditions.checkArgument(mFamilies.size() < getMaxCustomFallbackCount(),
                    "Custom fallback limit exceeded(" + getMaxCustomFallbackCount() + ")");
            mFamilies.add(family);
            return this;
        }

        /**
         * Create the Typeface based on the configured values.
         *
         * @return the Typeface object
         */
        public @NonNull Typeface build() {
            final int userFallbackSize = mFamilies.size();
            final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
            final long[] ptrArray = new long[fallback.length + userFallbackSize];
            for (int i = 0; i < userFallbackSize; ++i) {
                ptrArray[i] = mFamilies.get(i).getNativePtr();
            }
            for (int i = 0; i < fallback.length; ++i) {
                ptrArray[i + userFallbackSize] = fallback[i].getNativePtr();
            }
            final int weight = mStyle == null ? 400 : mStyle.getWeight();
            final int italic =
                    (mStyle == null || mStyle.getSlant() == FontStyle.FONT_SLANT_UPRIGHT) ?  0 : 1;
            return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
        }
    }

    /**
     * Create a typeface object given a family name, and option style information.
     * If null is passed for the name, then the "default" font will be chosen.
     * The resulting typeface object can be queried (getStyle()) to discover what
     * its "real" style characteristics are.
     *
     * @param familyName May be null. The name of the font family.
     * @param style  The style (normal, bold, italic) of the typeface.
     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
     * @return The best matching typeface.
     */
    public static Typeface create(String familyName, @Style int style) {
        return create(getSystemDefaultTypeface(familyName), style);
    }

    /**
     * Create a typeface object that best matches the specified existing
     * typeface and the specified Style. Use this call if you want to pick a new
     * style from the same family of an existing typeface object. If family is
     * null, this selects from the default font's family.
     *
     * <p>
     * This method is not thread safe on API 27 or before.
     * This method is thread safe on API 28 or after.
     * </p>
     *
     * @param family An existing {@link Typeface} object. In case of {@code null}, the default
     *               typeface is used instead.
     * @param style  The style (normal, bold, italic) of the typeface.
     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
     * @return The best matching typeface.
     */
    public static Typeface create(Typeface family, @Style int style) {
        if ((style & ~STYLE_MASK) != 0) {
            style = NORMAL;
        }
        if (family == null) {
            family = sDefaultTypeface;
        }

        // Return early if we're asked for the same face/style
        if (family.mStyle == style) {
            return family;
        }

        final long ni = family.native_instance;

        Typeface typeface;
        synchronized (sStyledCacheLock) {
            SparseArray<Typeface> styles = sStyledTypefaceCache.get(ni);

            if (styles == null) {
                styles = new SparseArray<Typeface>(4);
                sStyledTypefaceCache.put(ni, styles);
            } else {
                typeface = styles.get(style);
                if (typeface != null) {
                    return typeface;
                }
            }

            typeface = new Typeface(nativeCreateFromTypeface(ni, style));
            styles.put(style, typeface);
        }
        return typeface;
    }

    /**
     * Creates a typeface object that best matches the specified existing typeface and the specified
     * weight and italic style
     * <p>Below are numerical values and corresponding common weight names.</p>
     * <table>
     * <thead>
     * <tr><th>Value</th><th>Common weight name</th></tr>
     * </thead>
     * <tbody>
     * <tr><td>100</td><td>Thin</td></tr>
     * <tr><td>200</td><td>Extra Light</td></tr>
     * <tr><td>300</td><td>Light</td></tr>
     * <tr><td>400</td><td>Normal</td></tr>
     * <tr><td>500</td><td>Medium</td></tr>
     * <tr><td>600</td><td>Semi Bold</td></tr>
     * <tr><td>700</td><td>Bold</td></tr>
     * <tr><td>800</td><td>Extra Bold</td></tr>
     * <tr><td>900</td><td>Black</td></tr>
     * </tbody>
     * </table>
     *
     * <p>
     * This method is thread safe.
     * </p>
     *
     * @param family An existing {@link Typeface} object. In case of {@code null}, the default
     *               typeface is used instead.
     * @param weight The desired weight to be drawn.
     * @param italic {@code true} if italic style is desired to be drawn. Otherwise, {@code false}
     * @return A {@link Typeface} object for drawing specified weight and italic style. Never
     *         returns {@code null}
     *
     * @see #getWeight()
     * @see #isItalic()
     */
    public static @NonNull Typeface create(@Nullable Typeface family,
            @IntRange(from = 1, to = 1000) int weight, boolean italic) {
        Preconditions.checkArgumentInRange(weight, 0, 1000, "weight");
        if (family == null) {
            family = sDefaultTypeface;
        }
        return createWeightStyle(family, weight, italic);
    }

    private static @NonNull Typeface createWeightStyle(@NonNull Typeface base,
            @IntRange(from = 1, to = 1000) int weight, boolean italic) {
        final int key = (weight << 1) | (italic ? 1 : 0);

        Typeface typeface;
        synchronized(sWeightCacheLock) {
            SparseArray<Typeface> innerCache = sWeightTypefaceCache.get(base.native_instance);
            if (innerCache == null) {
                innerCache = new SparseArray<>(4);
                sWeightTypefaceCache.put(base.native_instance, innerCache);
            } else {
                typeface = innerCache.get(key);
                if (typeface != null) {
                    return typeface;
                }
            }

            typeface = new Typeface(
                    nativeCreateFromTypefaceWithExactStyle(base.native_instance, weight, italic));
            innerCache.put(key, typeface);
        }
        return typeface;
    }

    /** @hide */
    public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family,
            @NonNull List<FontVariationAxis> axes) {
        final Typeface base = family == null ? Typeface.DEFAULT : family;
        return new Typeface(nativeCreateFromTypefaceWithVariation(base.native_instance, axes));
    }

    /**
     * Returns one of the default typeface objects, based on the specified style
     *
     * @return the default typeface that corresponds to the style
     */
    public static Typeface defaultFromStyle(@Style int style) {
        return sDefaults[style];
    }

    /**
     * Create a new typeface from the specified font data.
     *
     * @param mgr  The application's asset manager
     * @param path The file name of the font data in the assets directory
     * @return The new typeface.
     */
    public static Typeface createFromAsset(AssetManager mgr, String path) {
        Preconditions.checkNotNull(path); // for backward compatibility
        Preconditions.checkNotNull(mgr);

        Typeface typeface = new Builder(mgr, path).build();
        if (typeface != null) return typeface;
        // check if the file exists, and throw an exception for backward compatibility
        try (InputStream inputStream = mgr.open(path)) {
        } catch (IOException e) {
            throw new RuntimeException("Font asset not found " + path);
        }

        return Typeface.DEFAULT;
    }

    /**
     * Creates a unique id for a given font provider and query.
     */
    private static String createProviderUid(String authority, String query) {
        final StringBuilder builder = new StringBuilder();
        builder.append("provider:");
        builder.append(authority);
        builder.append("-");
        builder.append(query);
        return builder.toString();
    }

    /**
     * Create a new typeface from the specified font file.
     *
     * @param file The path to the font data.
     * @return The new typeface.
     */
    public static Typeface createFromFile(@Nullable File file) {
        // For the compatibility reasons, leaving possible NPE here.
        // See android.graphics.cts.TypefaceTest#testCreateFromFileByFileReferenceNull

        Typeface typeface = new Builder(file).build();
        if (typeface != null) return typeface;

        // check if the file exists, and throw an exception for backward compatibility
        if (!file.exists()) {
            throw new RuntimeException("Font asset not found " + file.getAbsolutePath());
        }

        return Typeface.DEFAULT;
    }

    /**
     * Create a new typeface from the specified font file.
     *
     * @param path The full path to the font data.
     * @return The new typeface.
     */
    public static Typeface createFromFile(@Nullable String path) {
        Preconditions.checkNotNull(path); // for backward compatibility
        return createFromFile(new File(path));
    }

    /**
     * Create a new typeface from an array of font families.
     *
     * @param families array of font families
     * @deprecated
     */
    @Deprecated
    @UnsupportedAppUsage(trackingBug = 123768928)
    private static Typeface createFromFamilies(android.graphics.FontFamily[] families) {
        long[] ptrArray = new long[families.length];
        for (int i = 0; i < families.length; i++) {
            ptrArray[i] = families[i].mNativePtr;
        }
        return new Typeface(nativeCreateFromArray(
                ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
    }

    /**
     * Create a new typeface from an array of android.graphics.fonts.FontFamily.
     *
     * @param families array of font families
     */
    private static Typeface createFromFamilies(@Nullable FontFamily[] families) {
        final long[] ptrArray = new long[families.length];
        for (int i = 0; i < families.length; ++i) {
            ptrArray[i] = families[i].getNativePtr();
        }
        return new Typeface(nativeCreateFromArray(ptrArray,
                  RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
    }

    /**
     * This method is used by supportlib-v27.
     *
     * @deprecated Use {@link android.graphics.fonts.FontFamily} instead.
     */
    @UnsupportedAppUsage(trackingBug = 123768395)
    @Deprecated
    private static Typeface createFromFamiliesWithDefault(
            android.graphics.FontFamily[] families, int weight, int italic) {
        return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
    }

    /**
     * Create a new typeface from an array of font families, including
     * also the font families in the fallback list.
     * @param fallbackName the family name. If given families don't support characters, the
     *               characters will be rendered with this family.
     * @param weight the weight for this family. In that case, the table information in the first
     *               family's font is used. If the first family has multiple fonts, the closest to
     *               the regular weight and upright font is used.
     * @param italic the italic information for this family. In that case, the table information in
     *               the first family's font is used. If the first family has multiple fonts, the
     *               closest to the regular weight and upright font is used.
     * @param families array of font families
     *
     * @deprecated Use {@link android.graphics.fonts.FontFamily} instead.
     */
    @UnsupportedAppUsage(trackingBug = 123768928)
    @Deprecated
    private static Typeface createFromFamiliesWithDefault(android.graphics.FontFamily[] families,
                String fallbackName, int weight, int italic) {
        android.graphics.fonts.FontFamily[] fallback = SystemFonts.getSystemFallback(fallbackName);
        long[] ptrArray = new long[families.length + fallback.length];
        for (int i = 0; i < families.length; i++) {
            ptrArray[i] = families[i].mNativePtr;
        }
        for (int i = 0; i < fallback.length; i++) {
            ptrArray[i + families.length] = fallback[i].getNativePtr();
        }
        return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
    }

    // don't allow clients to call this directly
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private Typeface(long ni) {
        if (ni == 0) {
            throw new RuntimeException("native typeface cannot be made");
        }

        native_instance = ni;
        sRegistry.registerNativeAllocation(this, native_instance);
        mStyle = nativeGetStyle(ni);
        mWeight = nativeGetWeight(ni);
    }

    private static Typeface getSystemDefaultTypeface(@NonNull String familyName) {
        Typeface tf = sSystemFontMap.get(familyName);
        return tf == null ? Typeface.DEFAULT : tf;
    }

    /** @hide */
    @VisibleForTesting
    public static void initSystemDefaultTypefaces(Map<String, Typeface> systemFontMap,
            Map<String, FontFamily[]> fallbacks,
            FontConfig.Alias[] aliases) {
        for (Map.Entry<String, FontFamily[]> entry : fallbacks.entrySet()) {
            systemFontMap.put(entry.getKey(), createFromFamilies(entry.getValue()));
        }

        for (FontConfig.Alias alias : aliases) {
            if (systemFontMap.containsKey(alias.getName())) {
                continue; // If alias and named family are conflict, use named family.
            }
            final Typeface base = systemFontMap.get(alias.getToName());
            if (base == null) {
                // The missing target is a valid thing, some configuration don't have font files,
                // e.g. wear devices. Just skip this alias.
                continue;
            }
            final int weight = alias.getWeight();
            final Typeface newFace = weight == 400 ? base :
                    new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
            systemFontMap.put(alias.getName(), newFace);
        }
    }

    private static void registerGenericFamilyNative(@NonNull String familyName,
            @Nullable Typeface typeface) {
        if (typeface != null) {
            nativeRegisterGenericFamily(familyName, typeface.native_instance);
        }
    }

    static {
        final HashMap<String, Typeface> systemFontMap = new HashMap<>();
        initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
                SystemFonts.getAliases());
        sSystemFontMap = Collections.unmodifiableMap(systemFontMap);

        // We can't assume DEFAULT_FAMILY available on Roboletric.
        if (sSystemFontMap.containsKey(DEFAULT_FAMILY)) {
            setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
        }

        // Set up defaults and typefaces exposed in public API
        DEFAULT         = create((String) null, 0);
        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
        SANS_SERIF      = create("sans-serif", 0);
        SERIF           = create("serif", 0);
        MONOSPACE       = create("monospace", 0);

        sDefaults = new Typeface[] {
            DEFAULT,
            DEFAULT_BOLD,
            create((String) null, Typeface.ITALIC),
            create((String) null, Typeface.BOLD_ITALIC),
        };

        // A list of generic families to be registered in native.
        // https://www.w3.org/TR/css-fonts-4/#generic-font-families
        String[] genericFamilies = {
            "serif", "sans-serif", "cursive", "fantasy", "monospace", "system-ui"
        };

        for (String genericFamily : genericFamilies) {
            registerGenericFamilyNative(genericFamily, systemFontMap.get(genericFamily));
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Typeface typeface = (Typeface) o;

        return mStyle == typeface.mStyle && native_instance == typeface.native_instance;
    }

    @Override
    public int hashCode() {
        /*
         * Modified method for hashCode with long native_instance derived from
         * http://developer.android.com/reference/java/lang/Object.html
         */
        int result = 17;
        result = 31 * result + (int) (native_instance ^ (native_instance >>> 32));
        result = 31 * result + mStyle;
        return result;
    }

    /** @hide */
    public boolean isSupportedAxes(int axis) {
        if (mSupportedAxes == null) {
            synchronized (this) {
                if (mSupportedAxes == null) {
                    mSupportedAxes = nativeGetSupportedAxes(native_instance);
                    if (mSupportedAxes == null) {
                        mSupportedAxes = EMPTY_AXES;
                    }
                }
            }
        }
        return Arrays.binarySearch(mSupportedAxes, axis) >= 0;
    }

    private static native long nativeCreateFromTypeface(long native_instance, int style);
    private static native long nativeCreateFromTypefaceWithExactStyle(
            long native_instance, int weight, boolean italic);
    // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
    private static native long nativeCreateFromTypefaceWithVariation(
            long native_instance, List<FontVariationAxis> axes);
    @UnsupportedAppUsage
    private static native long nativeCreateWeightAlias(long native_instance, int weight);
    @UnsupportedAppUsage
    private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
    private static native int[] nativeGetSupportedAxes(long native_instance);

    @CriticalNative
    private static native void nativeSetDefault(long nativePtr);

    @CriticalNative
    private static native int  nativeGetStyle(long nativePtr);

    @CriticalNative
    private static native int  nativeGetWeight(long nativePtr);

    @CriticalNative
    private static native long nativeGetReleaseFunc();

    private static native void nativeRegisterGenericFamily(String str, long nativePtr);
}
