Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5a8e06f authored by Diego Perez's avatar Diego Perez Committed by Android (Google) Code Review
Browse files

Merge "Add dynamic font support"

parents 83e0faf2 789c4b4b
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.resources.ResourceType;
import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
@@ -696,6 +697,22 @@ public final class BridgeTypedArray extends TypedArray {
    }


    /**
     * Retrieve the Typeface for the attribute at <var>index</var>.
     * @param index Index of attribute to retrieve.
     *
     * @return Typeface for the attribute, or null if not defined.
     */
    @Override
    public Typeface getFont(int index) {
        if (!hasValue(index)) {
            return null;
        }

        ResourceValue value = mResourceData[index];
        return ResourceHelper.getFont(value, mContext, mTheme);
    }

    /**
     * Retrieve the CharSequence[] for the attribute at <var>index</var>.
     * This gets the resource ID of the selected attribute, and uses
+30 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.icu.text.PluralRules;
import android.util.AttributeSet;
@@ -778,6 +779,35 @@ public class Resources_Delegate {
        return getQuantityString(resources, id, quantity);
    }

    @LayoutlibDelegate
    static Typeface getFont(Resources resources, int id) throws
            NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
        if (value != null) {
            return ResourceHelper.getFont(value.getSecond(), resources.mContext, null);
        }

        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static Typeface getFont(Resources resources, TypedValue outValue, int id) throws
            NotFoundException {
        Resources_Delegate.getValue(resources, id, outValue, true);
        if (outValue.string != null) {
            return ResourceHelper.getFont(outValue.string.toString(), resources.mContext, null,
                    mPlatformResourceFlag[0]);
        }

        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
            throws NotFoundException {
+3 −1
Original line number Diff line number Diff line
@@ -344,7 +344,9 @@ public class FontFamily_Delegate {
                    ffd.addFont(fontInfo);
                    return true;
                }
                fontStream = assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING);
                fontStream = isAsset ?
                        assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING) :
                        assetRepository.openNonAsset(cookie, path, AssetManager.ACCESS_STREAMING);
                if (fontStream == null) {
                    Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
                            path);
+28 −0
Original line number Diff line number Diff line
/*
 * 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 android.graphics;

import android.annotation.NonNull;

/**
 * Class allowing access to package-protected methods/fields.
 */
public class Typeface_Accessor {
    public static boolean isSystemFont(@NonNull String fontName) {
        return Typeface.sSystemFontMap.containsKey(fontName);
    }
}
+87 −0
Original line number Diff line number Diff line
@@ -38,16 +38,20 @@ import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.content.res.ComplexColor;
import android.content.res.ComplexColor_Accessor;
import android.content.res.FontResourcesParser;
import android.content.res.GradientColor;
import android.content.res.Resources.Theme;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.NinePatch_Delegate;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Typeface_Accessor;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.text.FontConfig;
import android.util.TypedValue;

import java.io.File;
@@ -367,6 +371,89 @@ public final class ResourceHelper {
        return null;
    }

    /**
     * Returns a {@link Typeface} given a font name. The font name, can be a system font family
     * (like sans-serif) or a full path if the font is to be loaded from resources.
     */
    public static Typeface getFont(String fontName, BridgeContext context, Theme theme, boolean
            isFramework) {
        if (fontName == null) {
            return null;
        }

        if (Typeface_Accessor.isSystemFont(fontName)) {
            // Shortcut for the case where we are asking for a system font name. Those are not
            // loaded using external resources.
            return null;
        }

        // Check if this is an asset that we've already loaded dynamically
        Typeface typeface = Typeface.findFromCache(context.getAssets(), fontName);
        if (typeface != null) {
            return typeface;
        }

        String lowerCaseValue = fontName.toLowerCase();
        if (lowerCaseValue.endsWith(".xml")) {
            // create a block parser for the file
            Boolean psiParserSupport = context.getLayoutlibCallback().getFlag(
                    RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT);
            XmlPullParser parser = null;
            if (psiParserSupport != null && psiParserSupport) {
                parser = context.getLayoutlibCallback().getXmlFileParser(fontName);
            }
            else {
                File f = new File(fontName);
                if (f.isFile()) {
                    try {
                        parser = ParserFactory.create(f);
                    } catch (XmlPullParserException | FileNotFoundException e) {
                        // this is an error and not warning since the file existence is checked before
                        // attempting to parse it.
                        Bridge.getLog().error(null, "Failed to parse file " + fontName,
                                e, null /*data*/);
                    }
                }
            }

            if (parser != null) {
                BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
                        parser, context, isFramework);
                try {
                    FontConfig config = FontResourcesParser.parse(blockParser, context
                            .getResources());
                    typeface = Typeface.createFromResources(config, context.getAssets(),
                            fontName);
                } catch (XmlPullParserException | IOException e) {
                    Bridge.getLog().error(null, "Failed to parse file " + fontName,
                            e, null /*data*/);
                } finally {
                    blockParser.ensurePopped();
                }
            } else {
                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
                        String.format("File %s does not exist (or is not a file)", fontName),
                        null /*data*/);
            }
        } else {
            typeface = Typeface.createFromResources(context.getAssets(), fontName, 0);
        }

        return typeface;
    }

    /**
     * Returns a {@link Typeface} given a font name. The font name, can be a system font family
     * (like sans-serif) or a full path if the font is to be loaded from resources.
     */
    public static Typeface getFont(ResourceValue value, BridgeContext context, Theme theme) {
        if (value == null) {
            return null;
        }

        return getFont(value.getValue(), context, theme, value.isFramework());
    }

    private static Drawable getNinePatchDrawable(InputStream inputStream, Density density,
            boolean isFramework, String cacheKey, BridgeContext context) throws IOException {
        // see if we still have both the chunk and the bitmap in the caches
Loading