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

Commit ad69aee5 authored by Deepanshu Gupta's avatar Deepanshu Gupta
Browse files

LayoutLib: Font variants

Update to support font variants properly.

Change-Id: Iabe37babd9ddce80a9ba9eca7e0e5a0ffb090646
parent c8e2d0a4
Loading
Loading
Loading
Loading
+41 −35
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.content.res.AssetManager;

import java.awt.Font;
import java.io.File;
import java.util.ArrayList;
@@ -47,7 +49,6 @@ public class FontFamily_Delegate {
    private static final String FONT_SUFFIX_BOLDITALIC = "BoldItalic.ttf";
    private static final String FONT_SUFFIX_BOLD = "Bold.ttf";
    private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
    private static final String FONT_SUBSTRING_COMPACT = "UI";

    /**
     * A class associating {@link Font} with its metadata.
@@ -56,11 +57,6 @@ public class FontFamily_Delegate {
        Font mFont;
        /** Regular, Bold, Italic, or BoldItalic. */
        int mStyle;
        /**
         * The variant of the Font - compact or elegant.
         * @see Paint#setElegantTextHeight(boolean)
         */
        boolean mIsCompact;
    }

    // ---- delegate manager ----
@@ -75,6 +71,14 @@ public class FontFamily_Delegate {

    // ---- delegate data ----
    private List<FontInfo> mFonts = new ArrayList<FontInfo>();
    /**
     * The variant of the Font Family - compact or elegant.
     * 0 is unspecified, 1 is compact and 2 is elegant. This needs to be kept in sync with values in
     * android.graphics.FontFamily
     *
     * @see Paint#setElegantTextHeight(boolean)
     */
    private FontVariant mVariant;
    // Path of fonts that haven't been created since sFontLoader hasn't been initialized.
    private List<String> mPath = new ArrayList<String>();

@@ -93,37 +97,22 @@ public class FontFamily_Delegate {
        sPostInitDelegate.clear();
    }

    public Font getFont(int style, boolean isCompact) {
    public Font getFont(int style) {
        FontInfo plainFont = null;
        FontInfo styledFont = null;  // Font matching the style but not isCompact
        for (FontInfo font : mFonts) {
            if (font.mStyle == style) {
                if (font.mIsCompact == isCompact) {
                return font.mFont;
            }
                styledFont = font;
            }
            if (font.mStyle == Font.PLAIN) {
                if (plainFont == null) {
                    plainFont = font;
                    continue;
                }
                if (font.mIsCompact == isCompact) {
                    // Override the previous selection of plain font since we've found a better one.
            if (font.mStyle == Font.PLAIN && plainFont == null) {
                plainFont = font;
            }
        }
        }
        if (styledFont != null) {
            return styledFont.mFont;
        }

        // No font with the mentioned style is found. Try to derive one.
        if (plainFont != null && style > 0 && style < 4) {
            styledFont = new FontInfo();
            FontInfo styledFont = new FontInfo();
            styledFont.mFont = plainFont.mFont.deriveFont(style);
            styledFont.mStyle = style;
            styledFont.mIsCompact = plainFont.mIsCompact;
            // Add the font to the list of fonts so that we don't have to derive it the next time.
            mFonts.add(styledFont);
            return styledFont.mFont;
@@ -131,11 +120,20 @@ public class FontFamily_Delegate {
        return null;
    }

    public FontVariant getVariant() {
        return mVariant;
    }


    // ---- native methods ----

    @LayoutlibDelegate
    /*package*/ static long nCreateFamily() {
    /*package*/ static long nCreateFamily(String lang, int variant) {
        // TODO: support lang. This is required for japanese locale.
        FontFamily_Delegate delegate = new FontFamily_Delegate();
        // variant can be 0, 1 or 2.
        assert variant < 3;
        delegate.mVariant = FontVariant.values()[variant];
        if (sFontLocation != null) {
            delegate.init();
        } else {
@@ -164,6 +162,13 @@ public class FontFamily_Delegate {
        return false;
    }

    @LayoutlibDelegate
    /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "FontFamily.addFontFromAsset is not supported.", null /*throwable*/, null /*data*/);
        return false;
    }

    private void init() {
        for (String path : mPath) {
            addFont(path);
@@ -195,13 +200,6 @@ public class FontFamily_Delegate {
            style = Font.ITALIC;
        }
        fontInfo.mStyle = style;

        // Names of compact fonts end with UI-<style>.ttf. For example, NotoNakshUI-Regular.ttf.
        // This should go away when this info is passed on by nAddFont().
        int hyphenIndex = fontName.lastIndexOf('-');
        fontInfo.mIsCompact = hyphenIndex > 0 &&
                fontName.substring(0, hyphenIndex).endsWith(FONT_SUBSTRING_COMPACT);

    }

    private static Font loadFont(String path) {
@@ -214,7 +212,7 @@ public class FontFamily_Delegate {
            } catch (Exception e) {
                Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
                        String.format("Unable to load font %1$s", relativePath),
                        null /*throwable*/, null /*data*/);
                        e /*throwable*/, null /*data*/);
            }
        } else {
            Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -224,4 +222,12 @@ public class FontFamily_Delegate {

        return null;
    }


    // ---- Public helper class ----

    public enum FontVariant {
        // The order needs to be kept in sync with android.graphics.FontFamily.
        NONE, COMPACT, ELEGANT
    }
}
+16 −15
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.graphics.FontFamily_Delegate.FontVariant;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.FontMetricsInt;
import android.text.TextUtils;
@@ -30,7 +31,6 @@ import java.awt.Font;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.Collections;
@@ -81,7 +81,8 @@ public class Paint_Delegate {
    private float mTextScaleX;
    private float mTextSkewX;
    private int mHintingMode = Paint.HINTING_ON;
    private boolean mIsCompact = true;
    // Variant of the font.
    private FontVariant mFontVariant = FontVariant.NONE;

    private Xfermode_Delegate mXfermode;
    private ColorFilter_Delegate mColorFilter;
@@ -437,7 +438,7 @@ public class Paint_Delegate {
    /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
        // get the delegate from the native int.
        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
        return delegate != null && !delegate.mIsCompact;
        return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
    }

    @LayoutlibDelegate
@@ -448,7 +449,7 @@ public class Paint_Delegate {
            return;
        }

        delegate.mIsCompact = !elegant;
        delegate.mFontVariant = elegant ? FontVariant.ELEGANT : FontVariant.COMPACT;
    }

    @LayoutlibDelegate
@@ -1022,31 +1023,31 @@ public class Paint_Delegate {
    }

    @LayoutlibDelegate
    /*package*/ static void native_getTextPath(long native_object, int bidiFlags,
                char[] text, int index, int count, float x, float y, long path) {
    /*package*/ static void native_getTextPath(long native_object, long native_typeface,
            int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Paint.getTextPath is not supported.", null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void native_getTextPath(long native_object, int bidiFlags,
            String text, int start, int end, float x, float y, long path) {
    /*package*/ static void native_getTextPath(long native_object, long native_typeface,
            int bidiFlags, String text, int start, int end, float x, float y, long path) {
        // FIXME
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                "Paint.getTextPath is not supported.", null, null /*data*/);
    }

    @LayoutlibDelegate
    /*package*/ static void nativeGetStringBounds(long nativePaint, String text, int start,
            int end, int bidiFlags, Rect bounds) {
        nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bidiFlags,
                bounds);
    /*package*/ static void nativeGetStringBounds(long nativePaint, long native_typeface,
            String text, int start, int end, int bidiFlags, Rect bounds) {
        nativeGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
                end - start, bidiFlags, bounds);
    }

    @LayoutlibDelegate
    /*package*/ static void nativeGetCharArrayBounds(long nativePaint, char[] text, int index,
            int count, int bidiFlags, Rect bounds) {
    /*package*/ static void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
            char[] text, int index, int count, int bidiFlags, Rect bounds) {

        // get the delegate from the native int.
        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
@@ -1124,7 +1125,7 @@ public class Paint_Delegate {
    private void updateFontObject() {
        if (mTypeface != null) {
            // Get the fonts from the TypeFace object.
            List<Font> fonts = mTypeface.getFonts(mIsCompact);
            List<Font> fonts = mTypeface.getFonts(mFontVariant);

            // create new font objects as well as FontMetrics, based on the current text size
            // and skew info.
+16 −4
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.content.res.AssetManager;
import android.graphics.FontFamily_Delegate.FontVariant;

import java.awt.Font;
import java.io.File;
@@ -69,18 +70,29 @@ public final class Typeface_Delegate {
        return sManager.getDelegate(nativeTypeface);
    }

    public List<Font> getFonts(boolean compact) {
    public List<Font> getFonts(FontVariant variant) {
        List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
        // If we are unable to find fonts matching the variant, we return the fonts from the
        // other variant since we always want to draw something, rather than nothing.
        // TODO: check this behaviour with platform.
        List<Font> otherVariantFonts = new ArrayList<Font>();
        for (FontFamily_Delegate ffd : mFontFamilies) {
            if (ffd != null) {
                Font font = ffd.getFont(mStyle, compact);
                Font font = ffd.getFont(mStyle);
                if (font != null) {
                    if (ffd.getVariant() == variant || ffd.getVariant() == FontVariant.NONE) {
                        fonts.add(font);
                    } else {
                        otherVariantFonts.add(font);
                    }
                }
            }
        }
        if (fonts.size() > 0) {
            return fonts;
        }
        return otherVariantFonts;
    }

    // ---- native methods ----