diff options
author | Seigo Nonaka <nona@google.com> | 2021-04-14 19:15:16 -0700 |
---|---|---|
committer | Seigo Nonaka <nona@google.com> | 2021-04-15 11:03:37 -0700 |
commit | b950a1f746c9e130c78eafefc9bfd7ec87da730f (patch) | |
tree | d16d7f3c1481d82227edcfb3cef1679ceb230db5 /native/android | |
parent | 9e2adae46b250980d3b5f4ece7f6e4bfc363a8b5 (diff) |
Update native font API to read updated font files.
Bug: 184974821
Test: atest NativeSystemFontTest
Change-Id: Ia7fdf6155e07445d7f16edb88fd2a7293e63080c
Diffstat (limited to 'native/android')
-rw-r--r-- | native/android/system_fonts.cpp | 102 |
1 files changed, 87 insertions, 15 deletions
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp index 48d738039696..60b0f1eeaf72 100644 --- a/native/android/system_fonts.cpp +++ b/native/android/system_fonts.cpp @@ -54,21 +54,51 @@ struct ParserState { 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 @@ void copyFont(const XmlDocUniquePtr& xmlDoc, const ParserState& state, AFont* ou 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 @@ bool findFirstFontNode(const XmlDocUniquePtr& doc, ParserState* state) { 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 @@ bool findNextFontNode(const XmlDocUniquePtr& xmlDoc, ParserState* state) { 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. |