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

Commit df3dcb61 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Make AFont_getLocale work"

parents c375c6b0 01709c74
Loading
Loading
Loading
Loading
+56 −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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import android.content.res.AssetManager;
import android.graphics.fonts.Font;

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

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.IOException;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class TypefaceEqualsTest {
    @Test
    public void testFontEqualWithLocale() throws IOException {
        final AssetManager am =
                InstrumentationRegistry.getInstrumentation().getContext().getAssets();

        Font masterFont = new Font.Builder(am, "fonts/a3em.ttf").build();

        Font jaFont = new Font.Builder(masterFont.getBuffer(), new File("fonts/a3em.ttf"), "ja")
                .build();
        Font jaFont2 = new Font.Builder(masterFont.getBuffer(), new File("fonts/a3em.ttf"), "ja")
                .build();
        Font koFont = new Font.Builder(masterFont.getBuffer(), new File("fonts/a3em.ttf"), "ko")
                .build();

        assertEquals(jaFont, jaFont2);
        assertNotEquals(jaFont, koFont);
        assertNotEquals(jaFont, masterFont);
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -519,12 +519,13 @@ public final class Font {
        }
        Font f = (Font) o;
        return mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
                && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer);
                && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer)
                && Objects.equals(f.mLocaleList, mLocaleList);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mFontStyle, mTtcIndex, Arrays.hashCode(mAxes), mBuffer);
        return Objects.hash(mFontStyle, mTtcIndex, Arrays.hashCode(mAxes), mBuffer, mLocaleList);
    }

    @Override
+35 −26
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#include <jni.h>

#define LOG_TAG "SystemFont"

#include <android/font.h>
#include <android/font_matcher.h>
#include <android/system_fonts.h>
@@ -47,9 +49,14 @@ struct XmlDocDeleter {
using XmlCharUniquePtr = std::unique_ptr<xmlChar, XmlCharDeleter>;
using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>;

struct ParserState {
    xmlNode* mFontNode = nullptr;
    XmlCharUniquePtr mLocale;
};

struct ASystemFontIterator {
    XmlDocUniquePtr mXmlDoc;
    xmlNode* mFontNode;
    ParserState state;

    // The OEM customization XML.
    XmlDocUniquePtr mCustomizationXmlDoc;
@@ -97,6 +104,7 @@ std::string xmlTrim(const std::string& in) {

const xmlChar* FAMILY_TAG = BAD_CAST("family");
const xmlChar* FONT_TAG = BAD_CAST("font");
const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang");

xmlNode* firstElement(xmlNode* node, const xmlChar* tag) {
    for (xmlNode* child = node->children; child; child = child->next) {
@@ -116,9 +124,9 @@ xmlNode* nextSibling(xmlNode* node, const xmlChar* tag) {
    return nullptr;
}

void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out,
void copyFont(const XmlDocUniquePtr& xmlDoc, const ParserState& state, AFont* out,
              const std::string& pathPrefix) {
    const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang");
    xmlNode* fontNode = state.mFontNode;
    XmlCharUniquePtr filePathStr(
            xmlNodeListGetString(xmlDoc.get(), fontNode->xmlChildrenNode, 1));
    out->mFilePath = pathPrefix + xmlTrim(
@@ -139,9 +147,10 @@ void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out,
    out->mCollectionIndex =  indexStr ?
            strtol(reinterpret_cast<const char*>(indexStr.get()), nullptr, 10) : 0;

    XmlCharUniquePtr localeStr(xmlGetProp(xmlDoc->parent, LOCALE_ATTR_NAME));
    out->mLocale.reset(
            localeStr ? new std::string(reinterpret_cast<const char*>(localeStr.get())) : nullptr);
            state.mLocale ?
            new std::string(reinterpret_cast<const char*>(state.mLocale.get()))
            : nullptr);

    const xmlChar* TAG_ATTR_NAME = BAD_CAST("tag");
    const xmlChar* STYLEVALUE_ATTR_NAME = BAD_CAST("stylevalue");
@@ -178,25 +187,27 @@ bool isFontFileAvailable(const std::string& filePath) {
    return S_ISREG(st.st_mode);
}

xmlNode* findFirstFontNode(const XmlDocUniquePtr& doc) {
bool findFirstFontNode(const XmlDocUniquePtr& doc, ParserState* state) {
    xmlNode* familySet = xmlDocGetRootElement(doc.get());
    if (familySet == nullptr) {
        return nullptr;
        return false;
    }
    xmlNode* family = firstElement(familySet, FAMILY_TAG);
    if (family == nullptr) {
        return nullptr;
        return false;
    }
    state->mLocale.reset(xmlGetProp(family, LOCALE_ATTR_NAME));

    xmlNode* font = firstElement(family, FONT_TAG);
    while (font == nullptr) {
        family = nextSibling(family, FAMILY_TAG);
        if (family == nullptr) {
            return nullptr;
            return false;
        }
        font = firstElement(family, FONT_TAG);
    }
    return font;
    state->mFontNode = font;
    return font != nullptr;
}

}  // namespace
@@ -272,38 +283,38 @@ AFont* _Nonnull AFontMatcher_match(
    return result.release();
}

xmlNode* findNextFontNode(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode) {
    if (fontNode == nullptr) {
bool findNextFontNode(const XmlDocUniquePtr& xmlDoc, ParserState* state) {
    if (state->mFontNode == nullptr) {
        if (!xmlDoc) {
            return nullptr;  // Already at the end.
            return false;  // Already at the end.
        } else {
            // First time to query font.
            return findFirstFontNode(xmlDoc);
            return findFirstFontNode(xmlDoc, state);
        }
    } else {
        xmlNode* nextNode = nextSibling(fontNode, FONT_TAG);
        xmlNode* nextNode = nextSibling(state->mFontNode, FONT_TAG);
        while (nextNode == nullptr) {
            xmlNode* family = nextSibling(fontNode->parent, FAMILY_TAG);
            xmlNode* family = nextSibling(state->mFontNode->parent, FAMILY_TAG);
            if (family == nullptr) {
                break;
            }
            state->mLocale.reset(xmlGetProp(family, LOCALE_ATTR_NAME));
            nextNode = firstElement(family, FONT_TAG);
        }
        return nextNode;
        state->mFontNode = nextNode;
        return nextNode != nullptr;
    }
}

AFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
    LOG_ALWAYS_FATAL_IF(ite == nullptr, "nullptr has passed as iterator argument");
    if (ite->mXmlDoc) {
        ite->mFontNode = findNextFontNode(ite->mXmlDoc, ite->mFontNode);
        if (ite->mFontNode == nullptr) {
        if (!findNextFontNode(ite->mXmlDoc, &ite->state)) {
            // Reached end of the XML file. Continue OEM customization.
            ite->mXmlDoc.reset();
            ite->mFontNode = nullptr;
        } else {
            std::unique_ptr<AFont> font = std::make_unique<AFont>();
            copyFont(ite->mXmlDoc, ite->mFontNode, font.get(), "/system/fonts/");
            copyFont(ite->mXmlDoc, ite->state, font.get(), "/system/fonts/");
            if (!isFontFileAvailable(font->mFilePath)) {
                return ASystemFontIterator_next(ite);
            }
@@ -312,15 +323,13 @@ AFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
    }
    if (ite->mCustomizationXmlDoc) {
        // TODO: Filter only customizationType="new-named-family"
        ite->mFontNode = findNextFontNode(ite->mCustomizationXmlDoc, ite->mFontNode);
        if (ite->mFontNode == nullptr) {
        if (!findNextFontNode(ite->mCustomizationXmlDoc, &ite->state)) {
            // Reached end of the XML file. Finishing
            ite->mCustomizationXmlDoc.reset();
            ite->mFontNode = nullptr;
            return nullptr;
        } else {
            std::unique_ptr<AFont> font = std::make_unique<AFont>();
            copyFont(ite->mCustomizationXmlDoc, ite->mFontNode, font.get(), "/product/fonts/");
            copyFont(ite->mCustomizationXmlDoc, ite->state, font.get(), "/product/fonts/");
            if (!isFontFileAvailable(font->mFilePath)) {
                return ASystemFontIterator_next(ite);
            }
@@ -351,7 +360,7 @@ bool AFont_isItalic(const AFont* font) {

const char* AFont_getLocale(const AFont* font) {
    LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
    return font->mLocale ? nullptr : font->mLocale->c_str();
    return font->mLocale ? font->mLocale->c_str() : nullptr;
}

size_t AFont_getCollectionIndex(const AFont* font) {