From 1c9947b80e296297103177389063f799da6edafa Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 27 Mar 2025 22:52:37 +0000 Subject: [PATCH] Android: Use AFontMatcher to locate generic system fonts on supported platforms --- .../native/juce_Fonts_android.cpp | 101 ++++++++++-------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/modules/juce_graphics/native/juce_Fonts_android.cpp b/modules/juce_graphics/native/juce_Fonts_android.cpp index 207e482856..6ef01ec3bc 100644 --- a/modules/juce_graphics/native/juce_Fonts_android.cpp +++ b/modules/juce_graphics/native/juce_Fonts_android.cpp @@ -35,23 +35,6 @@ namespace juce { -Typeface::Ptr Font::Native::getDefaultPlatformTypefaceForFont (const Font& font) -{ - Font f (font); - f.setTypefaceName ([&]() -> String - { - const auto faceName = font.getTypefaceName(); - - if (faceName == Font::getDefaultSansSerifFontName()) return "Roboto"; - if (faceName == Font::getDefaultSerifFontName()) return "Roboto"; - if (faceName == Font::getDefaultMonospacedFontName()) return "Roboto"; - - return faceName; - }()); - - return Typeface::createSystemTypefaceFor (f); -} - //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ STATICMETHOD (create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \ @@ -100,6 +83,11 @@ DECLARE_JNI_CLASS (JavaMessageDigest, "java/security/MessageDigest") DECLARE_JNI_CLASS (AndroidAssetManager, "android/content/res/AssetManager") #undef JNI_CLASS_MEMBERS +#define JUCE_INTRODUCED_IN_29 \ + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE("-Wgnu-zero-variadic-macro-arguments") \ + __INTRODUCED_IN (29) \ + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + // Defined in juce_core std::unique_ptr makeAndroidInputStreamWrapper (LocalRef stream); @@ -313,6 +301,23 @@ public: return from (FontOptions{}.withName ("Roboto")); } + static JUCE_INTRODUCED_IN_29 Typeface::Ptr findGenericTypefaceWithMatcher (const char* name) + { + using AFontMatcherPtr = std::unique_ptr>; + using AFontPtr = std::unique_ptr>; + + constexpr uint16_t testString[] { 't', 'e', 's', 't' }; + + const AFontMatcherPtr matcher { AFontMatcher_create() }; + const AFontPtr matched { AFontMatcher_match (matcher.get(), + name, + testString, + std::size (testString), + nullptr) }; + + return fromMatchedFont (matched.get()); + } + private: enum class DoCache { @@ -320,14 +325,7 @@ private: yes }; - // The definition of __BIONIC_AVAILABILITY was changed in NDK 28.1 and it now has variadic - // parameters. - // - // But __INTRODUCED_IN only has one parameter so there isn't even a way to pass on anything to - // to __BIONIC_AVAILABILITY. - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wgnu-zero-variadic-macro-arguments") - - static __INTRODUCED_IN (29) Typeface::Ptr fromMatchedFont (AFont* matched) + static JUCE_INTRODUCED_IN_29 Typeface::Ptr fromMatchedFont (AFont* matched) { if (matched == nullptr) { @@ -348,24 +346,12 @@ private: return cache->get ({ matchedFile, (int) matchedIndex }, &loadCompatibleFont); } - static __INTRODUCED_IN (29) Typeface::Ptr findSystemTypefaceWithMatcher() + static JUCE_INTRODUCED_IN_29 Typeface::Ptr findSystemTypefaceWithMatcher() { - using AFontMatcherPtr = std::unique_ptr>; - using AFontPtr = std::unique_ptr>; - - constexpr uint16_t testString[] { 't', 'e', 's', 't' }; - - const AFontMatcherPtr matcher { AFontMatcher_create() }; - const AFontPtr matched { AFontMatcher_match (matcher.get(), - "system-ui", - testString, - std::size (testString), - nullptr) }; - - return fromMatchedFont (matched.get()); + return findGenericTypefaceWithMatcher ("system-ui"); } - __INTRODUCED_IN (29) Typeface::Ptr matchWithAFontMatcher (const String& text, const String& language) const + JUCE_INTRODUCED_IN_29 Typeface::Ptr matchWithAFontMatcher (const String& text, const String& language) const { using AFontMatcherPtr = std::unique_ptr>; using AFontPtr = std::unique_ptr>; @@ -391,8 +377,6 @@ private: return fromMatchedFont (matched.get()); } - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - static bool shouldStoreAndroidFont (hb_face_t* face) { return (hb_ot_color_has_svg (face) || hb_ot_color_has_paint (face)) @@ -803,4 +787,37 @@ void Typeface::scanFolderForFonts (const File&) jassertfalse; // not currently available } +//============================================================================== +Typeface::Ptr Font::Native::getDefaultPlatformTypefaceForFont (const Font& font) +{ + const auto faceName = font.getTypefaceName(); + + const auto idealFace = std::invoke ([&]() -> Typeface::Ptr + { + if (__builtin_available (android 29, *)) + { + if (faceName == Font::getDefaultSansSerifFontName()) return AndroidTypeface::findGenericTypefaceWithMatcher ("sans-serif"); + if (faceName == Font::getDefaultSerifFontName()) return AndroidTypeface::findGenericTypefaceWithMatcher ("serif"); + if (faceName == Font::getDefaultMonospacedFontName()) return AndroidTypeface::findGenericTypefaceWithMatcher ("monospace"); + } + + return nullptr; + }); + + if (idealFace != nullptr) + return idealFace; + + Font f (font); + f.setTypefaceName (std::invoke ([&]() -> String + { + if (faceName == Font::getDefaultSansSerifFontName()) return "Roboto"; + if (faceName == Font::getDefaultSerifFontName()) return "Roboto"; + if (faceName == Font::getDefaultMonospacedFontName()) return "Roboto"; + + return faceName; + })); + + return Typeface::createSystemTypefaceFor (f); +} + } // namespace juce