Update native font API to read updated font files.
Bug: 184974821
Test: atest NativeSystemFontTest
Change-Id: Ia7fdf6155e07445d7f16edb88fd2a7293e63080c
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 48d7380..60b0f1e 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -54,21 +54,51 @@
XmlCharUniquePtr mLocale;
};
-struct ASystemFontIterator {
- XmlDocUniquePtr mXmlDoc;
- ParserState state;
-
- // The OEM customization XML.
- XmlDocUniquePtr mCustomizationXmlDoc;
-};
-
struct AFont {
std::string mFilePath;
- std::unique_ptr<std::string> mLocale;
+ std::optional<std::string> mLocale;
uint16_t mWeight;
bool mItalic;
uint32_t mCollectionIndex;
std::vector<std::pair<uint32_t, float>> mAxes;
+
+ bool operator==(const AFont& o) const {
+ return mFilePath == o.mFilePath && mLocale == o.mLocale && mWeight == o.mWeight &&
+ mItalic == o.mItalic && mCollectionIndex == o.mCollectionIndex && mAxes == o.mAxes;
+ }
+
+ AFont() = default;
+ AFont(const AFont&) = default;
+};
+
+struct FontHasher {
+ std::size_t operator()(const AFont& font) const {
+ std::size_t r = std::hash<std::string>{}(font.mFilePath);
+ if (font.mLocale) {
+ r = combine(r, std::hash<std::string>{}(*font.mLocale));
+ }
+ r = combine(r, std::hash<uint16_t>{}(font.mWeight));
+ r = combine(r, std::hash<uint32_t>{}(font.mCollectionIndex));
+ for (const auto& [tag, value] : font.mAxes) {
+ r = combine(r, std::hash<uint32_t>{}(tag));
+ r = combine(r, std::hash<float>{}(value));
+ }
+ return r;
+ }
+
+ std::size_t combine(std::size_t l, std::size_t r) const { return l ^ (r << 1); }
+};
+
+struct ASystemFontIterator {
+ std::vector<AFont> fonts;
+ uint32_t index;
+
+ XmlDocUniquePtr mXmlDoc;
+
+ ParserState state;
+
+ // The OEM customization XML.
+ XmlDocUniquePtr mCustomizationXmlDoc;
};
struct AFontMatcher {
@@ -147,10 +177,9 @@
out->mCollectionIndex = indexStr ?
strtol(reinterpret_cast<const char*>(indexStr.get()), nullptr, 10) : 0;
- out->mLocale.reset(
- state.mLocale ?
- new std::string(reinterpret_cast<const char*>(state.mLocale.get()))
- : nullptr);
+ if (state.mLocale) {
+ out->mLocale.emplace(reinterpret_cast<const char*>(state.mLocale.get()));
+ }
const xmlChar* TAG_ATTR_NAME = BAD_CAST("tag");
const xmlChar* STYLEVALUE_ATTR_NAME = BAD_CAST("stylevalue");
@@ -214,8 +243,44 @@
ASystemFontIterator* ASystemFontIterator_open() {
std::unique_ptr<ASystemFontIterator> ite(new ASystemFontIterator());
- ite->mXmlDoc.reset(xmlReadFile("/system/etc/fonts.xml", nullptr, 0));
- ite->mCustomizationXmlDoc.reset(xmlReadFile("/product/etc/fonts_customization.xml", nullptr, 0));
+
+ std::unordered_set<AFont, FontHasher> fonts;
+ minikin::SystemFonts::getFontMap(
+ [&fonts](const std::vector<std::shared_ptr<minikin::FontCollection>>& collections) {
+ for (const auto& fc : collections) {
+ for (const auto& family : fc->getFamilies()) {
+ for (uint32_t i = 0; i < family->getNumFonts(); ++i) {
+ const minikin::Font* font = family->getFont(i);
+
+ std::optional<std::string> locale;
+ uint32_t localeId = font->getLocaleListId();
+ if (localeId != minikin::kEmptyLocaleListId) {
+ locale.emplace(minikin::getLocaleString(localeId));
+ }
+ std::vector<std::pair<uint32_t, float>> axes;
+ for (const auto& [tag, value] : font->typeface()->GetAxes()) {
+ axes.push_back(std::make_pair(tag, value));
+ }
+
+ fonts.insert(
+ {font->typeface()->GetFontPath(), std::move(locale),
+ font->style().weight(),
+ font->style().slant() == minikin::FontStyle::Slant::ITALIC,
+ static_cast<uint32_t>(font->typeface()->GetFontIndex()),
+ axes});
+ }
+ }
+ }
+ });
+
+ if (fonts.empty()) {
+ ite->mXmlDoc.reset(xmlReadFile("/system/etc/fonts.xml", nullptr, 0));
+ ite->mCustomizationXmlDoc.reset(
+ xmlReadFile("/product/etc/fonts_customization.xml", nullptr, 0));
+ } else {
+ ite->index = 0;
+ ite->fonts.assign(fonts.begin(), fonts.end());
+ }
return ite.release();
}
@@ -308,6 +373,13 @@
AFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
LOG_ALWAYS_FATAL_IF(ite == nullptr, "nullptr has passed as iterator argument");
+ if (!ite->fonts.empty()) {
+ if (ite->index >= ite->fonts.size()) {
+ return nullptr;
+ }
+ return new AFont(ite->fonts[ite->index++]);
+ }
+
if (ite->mXmlDoc) {
if (!findNextFontNode(ite->mXmlDoc, &ite->state)) {
// Reached end of the XML file. Continue OEM customization.