Implement matchFamilyStyleCharacter API

Bug: 114479228
Test: atest CtsGraphicsTestCases:android.graphics.fonts
Change-Id: Ieaa4251e0ba7c0479f048147141a81766016e9b6
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 24d003b..a4306fe 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -62,8 +62,10 @@
         "libbinder",
         "libui",
         "libgui",
+        "libharfbuzz_ng",  // Only for including hb.h via minikin
         "libsensor",
         "libandroid_runtime",
+        "libminikin",
         "libnetd_client",
         "libhwui",
         "libxml2",
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 9f48bc9..e7e8384 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -224,6 +224,7 @@
     ASystemFont_getAxisCount; # introduced=29
     ASystemFont_getAxisTag; # introduced=29
     ASystemFont_getAxisValue; # introduced=29
+    ASystemFont_matchFamilyStyleCharacter; # introduced=29
     ATrace_beginSection; # introduced=23
     ATrace_endSection; # introduced=23
     ATrace_isEnabled; # introduced=23
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 761a475..4d3d1d6 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -29,6 +29,11 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <hwui/MinikinSkia.h>
+#include <minikin/FontCollection.h>
+#include <minikin/LocaleList.h>
+#include <minikin/SystemFonts.h>
+
 struct XmlCharDeleter {
     void operator()(xmlChar* b) { xmlFree(b); }
 };
@@ -192,6 +197,41 @@
     delete ite;
 }
 
+ASystemFont* ASystemFont_matchFamilyStyleCharacter(
+        const char* _Nonnull familyName,
+        uint16_t weight,
+        bool italic,
+        const char* _Nonnull languageTags,
+        const uint16_t* _Nonnull text,
+        uint32_t textLength,
+        uint32_t* _Nullable runLength) {
+    std::shared_ptr<minikin::FontCollection> fc =
+            minikin::SystemFonts::findFontCollection(familyName);
+    std::vector<minikin::FontCollection::Run> runs =
+            fc->itemize(minikin::U16StringPiece(text, textLength),
+                        minikin::FontStyle(weight, static_cast<minikin::FontStyle::Slant>(italic)),
+                        minikin::registerLocaleList(languageTags),
+                        minikin::FamilyVariant::DEFAULT);
+
+    const minikin::Font* font = runs[0].fakedFont.font;
+    std::unique_ptr<ASystemFont> result = std::make_unique<ASystemFont>();
+    const android::MinikinFontSkia* minikinFontSkia =
+            reinterpret_cast<android::MinikinFontSkia*>(font->typeface().get());
+    result->mFilePath = minikinFontSkia->getFilePath();
+    result->mWeight = font->style().weight();
+    result->mItalic = font->style().slant() == minikin::FontStyle::Slant::ITALIC;
+    result->mCollectionIndex = minikinFontSkia->GetFontIndex();
+    const std::vector<minikin::FontVariation>& axes = minikinFontSkia->GetAxes();
+    result->mAxes.reserve(axes.size());
+    for (auto axis : axes) {
+        result->mAxes.push_back(std::make_pair(axis.axisTag, axis.value));
+    }
+    if (runLength != nullptr) {
+        *runLength = runs[0].end;
+    }
+    return result.release();
+}
+
 xmlNode* findNextFontNode(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode) {
     if (fontNode == nullptr) {
         if (!xmlDoc) {