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

Commit 4983ed15 authored by Kohsuke Yatoh's avatar Kohsuke Yatoh Committed by Automerger Merge Worker
Browse files

Merge "Add FontListParser#writeFamily()." into sc-dev am: 5d2f4fc3

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13524650

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I68ef317b76ab700e32555a5793a0a173a5026dd2
parents bd5d7fe0 5d2f4fc3
Loading
Loading
Loading
Loading
+110 −4
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Objects;




/**
/**
@@ -155,6 +156,32 @@ public final class FontConfig implements Parcelable {
        }
        }
    };
    };


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FontConfig that = (FontConfig) o;
        return mLastModifiedTimeMillis == that.mLastModifiedTimeMillis
                && mConfigVersion == that.mConfigVersion
                && Objects.equals(mFamilies, that.mFamilies)
                && Objects.equals(mAliases, that.mAliases);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mFamilies, mAliases, mLastModifiedTimeMillis, mConfigVersion);
    }

    @Override
    public String toString() {
        return "FontConfig{"
                + "mFamilies=" + mFamilies
                + ", mAliases=" + mAliases
                + ", mLastModifiedTimeMillis=" + mLastModifiedTimeMillis
                + ", mConfigVersion=" + mConfigVersion
                + '}';
    }

    /**
    /**
     * Represents single font entry in system font configuration.
     * Represents single font entry in system font configuration.
     *
     *
@@ -317,6 +344,37 @@ public final class FontConfig implements Parcelable {
        public boolean isItalic() {
        public boolean isItalic() {
            return getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC;
            return getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC;
        }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Font font = (Font) o;
            return mIndex == font.mIndex
                    && Objects.equals(mFile, font.mFile)
                    && Objects.equals(mOriginalFile, font.mOriginalFile)
                    && Objects.equals(mStyle, font.mStyle)
                    && Objects.equals(mFontVariationSettings, font.mFontVariationSettings)
                    && Objects.equals(mFontFamilyName, font.mFontFamilyName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mFile, mOriginalFile, mStyle, mIndex, mFontVariationSettings,
                    mFontFamilyName);
        }

        @Override
        public String toString() {
            return "Font{"
                    + "mFile=" + mFile
                    + ", mOriginalFile=" + mOriginalFile
                    + ", mStyle=" + mStyle
                    + ", mIndex=" + mIndex
                    + ", mFontVariationSettings='" + mFontVariationSettings + '\''
                    + ", mFontFamilyName='" + mFontFamilyName + '\''
                    + '}';
        }
    }
    }


    /**
    /**
@@ -398,6 +456,30 @@ public final class FontConfig implements Parcelable {
                return new Alias[size];
                return new Alias[size];
            }
            }
        };
        };

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Alias alias = (Alias) o;
            return mWeight == alias.mWeight
                    && Objects.equals(mName, alias.mName)
                    && Objects.equals(mOriginal, alias.mOriginal);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mName, mOriginal, mWeight);
        }

        @Override
        public String toString() {
            return "Alias{"
                    + "mName='" + mName + '\''
                    + ", mOriginal='" + mOriginal + '\''
                    + ", mWeight=" + mWeight
                    + '}';
        }
    }
    }


    /**
    /**
@@ -413,7 +495,7 @@ public final class FontConfig implements Parcelable {
    public static final class FontFamily implements Parcelable {
    public static final class FontFamily implements Parcelable {
        private final @NonNull List<Font> mFonts;
        private final @NonNull List<Font> mFonts;
        private final @Nullable String mName;
        private final @Nullable String mName;
        private final @Nullable LocaleList mLocaleList;
        private final @NonNull LocaleList mLocaleList;
        private final @Variant int mVariant;
        private final @Variant int mVariant;


        /** @hide */
        /** @hide */
@@ -454,7 +536,7 @@ public final class FontConfig implements Parcelable {
         * @hide Only system server can create this instance and passed via IPC.
         * @hide Only system server can create this instance and passed via IPC.
         */
         */
        public FontFamily(@NonNull List<Font> fonts, @Nullable String name,
        public FontFamily(@NonNull List<Font> fonts, @Nullable String name,
                @Nullable LocaleList localeList, @Variant int variant) {
                @NonNull LocaleList localeList, @Variant int variant) {
            mFonts = fonts;
            mFonts = fonts;
            mName = name;
            mName = name;
            mLocaleList = localeList;
            mLocaleList = localeList;
@@ -493,8 +575,6 @@ public final class FontConfig implements Parcelable {
         *
         *
         * The locale list will be used for deciding which font family should be used in fallback
         * The locale list will be used for deciding which font family should be used in fallback
         * list.
         * list.
         *
         * @return non-null if a locale list is available. Otherwise null.
         */
         */
        public @NonNull LocaleList getLocaleList() {
        public @NonNull LocaleList getLocaleList() {
            return mLocaleList;
            return mLocaleList;
@@ -559,5 +639,31 @@ public final class FontConfig implements Parcelable {
        public @NonNull String getLanguages() {
        public @NonNull String getLanguages() {
            return mLocaleList.toLanguageTags();
            return mLocaleList.toLanguageTags();
        }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            FontFamily that = (FontFamily) o;
            return mVariant == that.mVariant
                    && Objects.equals(mFonts, that.mFonts)
                    && Objects.equals(mName, that.mName)
                    && Objects.equals(mLocaleList, that.mLocaleList);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mFonts, mName, mLocaleList, mVariant);
        }

        @Override
        public String toString() {
            return "FontFamily{"
                    + "mFonts=" + mFonts
                    + ", mName='" + mName + '\''
                    + ", mLocaleList=" + mLocaleList
                    + ", mVariant=" + mVariant
                    + '}';
        }
    }
    }
}
}
+245 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2021 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.graphics.fonts.FontStyle.FONT_SLANT_ITALIC;
import static android.graphics.fonts.FontStyle.FONT_SLANT_UPRIGHT;
import static android.graphics.fonts.FontStyle.FONT_WEIGHT_NORMAL;
import static android.text.FontConfig.FontFamily.VARIANT_COMPACT;
import static android.text.FontConfig.FontFamily.VARIANT_DEFAULT;
import static android.text.FontConfig.FontFamily.VARIANT_ELEGANT;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import android.graphics.fonts.FontStyle;
import android.os.LocaleList;
import android.text.FontConfig;
import android.util.TypedXmlSerializer;
import android.util.Xml;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FontListParserTest {

    @Test
    public void named() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family name='sans-serif'>"
                + "  <font>test.ttf</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null)),
                "sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void fallback() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family lang='en'>"
                + "  <font>test.ttf</font>"
                + "  <font fallbackFor='serif'>test.ttf</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null),
                        new FontConfig.Font(new File("test.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", "serif")),
                null, LocaleList.forLanguageTags("en"), VARIANT_DEFAULT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void compact() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family lang='en' variant='compact'>"
                + "  <font>test.ttf</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null)),
                null, LocaleList.forLanguageTags("en"), VARIANT_COMPACT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void elegant() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family lang='en' variant='elegant'>"
                + "  <font>test.ttf</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null)),
                null, LocaleList.forLanguageTags("en"), VARIANT_ELEGANT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void styles() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family name='sans-serif'>"
                + "  <font style='normal'>normal.ttf</font>"
                + "  <font weight='100'>weight.ttf</font>"
                + "  <font style='italic'>italic.ttf</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("normal.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null),
                        new FontConfig.Font(new File("weight.ttf"), null,
                                new FontStyle(100, FONT_SLANT_UPRIGHT),
                                0, "", null),
                        new FontConfig.Font(new File("italic.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC),
                                0, "", null)),
                "sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void variable() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family name='sans-serif'>"
                + "  <font>test-VF.ttf"
                + "    <axis tag='wdth' stylevalue='100' />"
                + "    <axis tag='wght' stylevalue='200' />"
                + "  </font>"
                + "  <font>test-VF.ttf"
                + "    <axis tag='wdth' stylevalue='400' />"
                + "    <axis tag='wght' stylevalue='700' />"
                + "  </font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test-VF.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "'wdth' 100.0,'wght' 200.0", null),
                        new FontConfig.Font(new File("test-VF.ttf"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "'wdth' 400.0,'wght' 700.0", null)),
                "sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    @Test
    public void ttc() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<family name='sans-serif'>"
                + "  <font index='0'>test.ttc</font>"
                + "  <font index='1'>test.ttc</font>"
                + "</family>";
        FontConfig.FontFamily expected = new FontConfig.FontFamily(
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttc"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null),
                        new FontConfig.Font(new File("test.ttc"), null,
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                1, "", null)),
                "sans-serif", LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT);
        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);

        String serialized = writeFamily(family);
        assertWithMessage("serialized = " + serialized)
                .that(readFamily(serialized)).isEqualTo(expected);
    }

    private FontConfig.FontFamily readFamily(String xml)
            throws IOException, XmlPullParserException {
        StandardCharsets.UTF_8.name();
        ByteArrayInputStream buffer = new ByteArrayInputStream(
                xml.getBytes(StandardCharsets.UTF_8));
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(buffer, "UTF-8");
        parser.nextTag();
        return FontListParser.readFamily(parser, "", null);
    }

    private String writeFamily(FontConfig.FontFamily family) throws IOException {
        TypedXmlSerializer out = Xml.newFastSerializer();
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        out.setOutput(buffer, "UTF-8");
        out.startTag(null, "family");
        FontListParser.writeFamily(out, family);
        out.endTag(null, "family");
        out.endDocument();
        return buffer.toString("UTF-8");
    }
}
+95 −12
Original line number Original line Diff line number Diff line
@@ -25,6 +25,8 @@ import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
import android.os.Build;
import android.os.LocaleList;
import android.os.LocaleList;
import android.text.FontConfig;
import android.text.FontConfig;
import android.text.TextUtils;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.util.Xml;


import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
@@ -45,6 +47,27 @@ import java.util.regex.Pattern;
 */
 */
public class FontListParser {
public class FontListParser {


    // XML constants for FontFamily.
    private static final String ATTR_NAME = "name";
    private static final String ATTR_LANG = "lang";
    private static final String ATTR_VARIANT = "variant";
    private static final String TAG_FONT = "font";
    private static final String VARIANT_COMPACT = "compact";
    private static final String VARIANT_ELEGANT = "elegant";

    // XML constants for Font.
    public static final String ATTR_INDEX = "index";
    public static final String ATTR_WEIGHT = "weight";
    public static final String ATTR_STYLE = "style";
    public static final String ATTR_FALLBACK_FOR = "fallbackFor";
    public static final String STYLE_ITALIC = "italic";
    public static final String STYLE_NORMAL = "normal";
    public static final String TAG_AXIS = "axis";

    // XML constants for FontVariationAxis.
    public static final String ATTR_TAG = "tag";
    public static final String ATTR_STYLEVALUE = "stylevalue";

    /* Parse fallback list (no names) */
    /* Parse fallback list (no names) */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
    public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
@@ -148,7 +171,7 @@ public class FontListParser {
        while (parser.next() != XmlPullParser.END_TAG) {
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            final String tag = parser.getName();
            final String tag = parser.getName();
            if (tag.equals("font")) {
            if (tag.equals(TAG_FONT)) {
                fonts.add(readFont(parser, fontDir, updatableFontMap));
                fonts.add(readFont(parser, fontDir, updatableFontMap));
            } else {
            } else {
                skip(parser);
                skip(parser);
@@ -156,15 +179,41 @@ public class FontListParser {
        }
        }
        int intVariant = FontConfig.FontFamily.VARIANT_DEFAULT;
        int intVariant = FontConfig.FontFamily.VARIANT_DEFAULT;
        if (variant != null) {
        if (variant != null) {
            if (variant.equals("compact")) {
            if (variant.equals(VARIANT_COMPACT)) {
                intVariant = FontConfig.FontFamily.VARIANT_COMPACT;
                intVariant = FontConfig.FontFamily.VARIANT_COMPACT;
            } else if (variant.equals("elegant")) {
            } else if (variant.equals(VARIANT_ELEGANT)) {
                intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
                intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
            }
            }
        }
        }
        return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
        return new FontConfig.FontFamily(fonts, name, LocaleList.forLanguageTags(lang), intVariant);
    }
    }


    /**
     * Write a family tag representing {@code fontFamily}. The tag should be started by the caller.
     */
    public static void writeFamily(TypedXmlSerializer out, FontConfig.FontFamily fontFamily)
            throws IOException {
        if (!TextUtils.isEmpty(fontFamily.getName())) {
            out.attribute(null, ATTR_NAME, fontFamily.getName());
        }
        if (!fontFamily.getLocaleList().isEmpty()) {
            out.attribute(null, ATTR_LANG, fontFamily.getLocaleList().toLanguageTags());
        }
        switch (fontFamily.getVariant()) {
            case FontConfig.FontFamily.VARIANT_COMPACT:
                out.attribute(null, ATTR_VARIANT, VARIANT_COMPACT);
                break;
            case FontConfig.FontFamily.VARIANT_ELEGANT:
                out.attribute(null, ATTR_VARIANT, VARIANT_ELEGANT);
                break;
        }
        for (FontConfig.Font font : fontFamily.getFontList()) {
            out.startTag(null, TAG_FONT);
            writeFont(out, font);
            out.endTag(null, TAG_FONT);
        }
    }

    /** Matches leading and trailing XML whitespace. */
    /** Matches leading and trailing XML whitespace. */
    private static final Pattern FILENAME_WHITESPACE_PATTERN =
    private static final Pattern FILENAME_WHITESPACE_PATTERN =
            Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
            Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
@@ -175,13 +224,13 @@ public class FontListParser {
            @Nullable Map<String, File> updatableFontMap)
            @Nullable Map<String, File> updatableFontMap)
            throws XmlPullParserException, IOException {
            throws XmlPullParserException, IOException {


        String indexStr = parser.getAttributeValue(null, "index");
        String indexStr = parser.getAttributeValue(null, ATTR_INDEX);
        int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
        int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
        List<FontVariationAxis> axes = new ArrayList<>();
        List<FontVariationAxis> axes = new ArrayList<>();
        String weightStr = parser.getAttributeValue(null, "weight");
        String weightStr = parser.getAttributeValue(null, ATTR_WEIGHT);
        int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
        int weight = weightStr == null ? FontStyle.FONT_WEIGHT_NORMAL : Integer.parseInt(weightStr);
        boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
        boolean isItalic = STYLE_ITALIC.equals(parser.getAttributeValue(null, ATTR_STYLE));
        String fallbackFor = parser.getAttributeValue(null, "fallbackFor");
        String fallbackFor = parser.getAttributeValue(null, ATTR_FALLBACK_FOR);
        StringBuilder filename = new StringBuilder();
        StringBuilder filename = new StringBuilder();
        while (parser.next() != XmlPullParser.END_TAG) {
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() == XmlPullParser.TEXT) {
            if (parser.getEventType() == XmlPullParser.TEXT) {
@@ -189,7 +238,7 @@ public class FontListParser {
            }
            }
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            String tag = parser.getName();
            String tag = parser.getName();
            if (tag.equals("axis")) {
            if (tag.equals(TAG_AXIS)) {
                axes.add(readAxis(parser));
                axes.add(readAxis(parser));
            } else {
            } else {
                skip(parser);
                skip(parser);
@@ -237,14 +286,48 @@ public class FontListParser {
        return null;
        return null;
    }
    }


    private static void writeFont(TypedXmlSerializer out, FontConfig.Font font)
            throws IOException {
        if (font.getTtcIndex() != 0) {
            out.attributeInt(null, ATTR_INDEX, font.getTtcIndex());
        }
        if (font.getStyle().getWeight() != FontStyle.FONT_WEIGHT_NORMAL) {
            out.attributeInt(null, ATTR_WEIGHT, font.getStyle().getWeight());
        }
        if (font.getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC) {
            out.attribute(null, ATTR_STYLE, STYLE_ITALIC);
        } else {
            out.attribute(null, ATTR_STYLE, STYLE_NORMAL);
        }
        if (!TextUtils.isEmpty(font.getFontFamilyName())) {
            out.attribute(null, ATTR_FALLBACK_FOR, font.getFontFamilyName());
        }
        out.text(font.getFile().getName());
        FontVariationAxis[] axes =
                FontVariationAxis.fromFontVariationSettings(font.getFontVariationSettings());
        if (axes != null) {
            for (FontVariationAxis axis : axes) {
                out.startTag(null, TAG_AXIS);
                writeAxis(out, axis);
                out.endTag(null, TAG_AXIS);
            }
        }
    }

    private static FontVariationAxis readAxis(XmlPullParser parser)
    private static FontVariationAxis readAxis(XmlPullParser parser)
            throws XmlPullParserException, IOException {
            throws XmlPullParserException, IOException {
        String tagStr = parser.getAttributeValue(null, "tag");
        String tagStr = parser.getAttributeValue(null, ATTR_TAG);
        String styleValueStr = parser.getAttributeValue(null, "stylevalue");
        String styleValueStr = parser.getAttributeValue(null, ATTR_STYLEVALUE);
        skip(parser);  // axis tag is empty, ignore any contents and consume end tag
        skip(parser);  // axis tag is empty, ignore any contents and consume end tag
        return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
        return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
    }
    }


    private static void writeAxis(TypedXmlSerializer out, FontVariationAxis axis)
            throws IOException {
        out.attribute(null, ATTR_TAG, axis.getTag());
        out.attributeFloat(null, ATTR_STYLEVALUE, axis.getStyleValue());
    }

    /**
    /**
     * Reads alias elements
     * Reads alias elements
     */
     */
@@ -255,7 +338,7 @@ public class FontListParser {
        String weightStr = parser.getAttributeValue(null, "weight");
        String weightStr = parser.getAttributeValue(null, "weight");
        int weight;
        int weight;
        if (weightStr == null) {
        if (weightStr == null) {
            weight = 400;
            weight = FontStyle.FONT_WEIGHT_NORMAL;
        } else {
        } else {
            weight = Integer.parseInt(weightStr);
            weight = Integer.parseInt(weightStr);
        }
        }