|
21 | 21 | #include "utils/FontUtils.h" |
22 | 22 | #include "utils/StringUtils.h" |
23 | 23 | #include "utils/URIUtils.h" |
| 24 | +#include "utils/XBMCTinyXML2.h" |
24 | 25 | #include "utils/log.h" |
25 | 26 |
|
26 | 27 | #include <algorithm> |
@@ -92,10 +93,82 @@ void CDVDSubtitlesLibass::Configure() |
92 | 93 | ass_set_margins(m_renderer, 0, 0, 0, 0); |
93 | 94 | ass_set_use_margins(m_renderer, 0); |
94 | 95 |
|
95 | | - // Libass uses system font provider (like fontconfig) by default in some |
96 | | - // platforms (e.g. linux/windows), on some other systems like android the |
97 | | - // font provider is currently not supported, then an user can add his |
98 | | - // additional fonts only by using the user fonts folder. |
| 96 | + int fontProvider = ASS_FONTPROVIDER_AUTODETECT; |
| 97 | + std::string fontconfigPath; // Keep string alive for lifetime of fontconfigConfig pointer |
| 98 | + const char* fontconfigConfig = nullptr; |
| 99 | + |
| 100 | +#if defined(TARGET_ANDROID) |
| 101 | + // Libass uses system font provider (like fontconfig) by default on some platforms (e.g. Linux/Windows), |
| 102 | + // but on Android the font provider is currently not supported by libass. |
| 103 | + // Workaround: Use fontconfig with a custom configuration pointing to Android system fonts, |
| 104 | + // enabling automatic font fallback for subtitles with non-Latin scripts. |
| 105 | + // This is a temporary workaround until libass implements native Android font provider support. |
| 106 | + fontProvider = ASS_FONTPROVIDER_FONTCONFIG; |
| 107 | + |
| 108 | + // Write fontconfig configuration to temp directory |
| 109 | + fontconfigPath = CSpecialProtocol::TranslatePath("special://temp/fonts.conf"); |
| 110 | + |
| 111 | + if (!XFILE::CFile::Exists(fontconfigPath)) |
| 112 | + { |
| 113 | + // Create fontconfig cache directory |
| 114 | + const std::string fontconfigCacheDir = |
| 115 | + CSpecialProtocol::TranslatePath("special://temp/fontconfig"); |
| 116 | + if (!XFILE::CDirectory::Exists(fontconfigCacheDir)) |
| 117 | + XFILE::CDirectory::Create(fontconfigCacheDir); |
| 118 | + |
| 119 | + // Create fontconfig configuration using XML library |
| 120 | + CXBMCTinyXML2 xmlDoc; |
| 121 | + xmlDoc.InsertEndChild(xmlDoc.NewDeclaration("xml version=\"1.0\"")); |
| 122 | + xmlDoc.InsertEndChild(xmlDoc.NewUnknown("DOCTYPE fontconfig SYSTEM \"fonts.dtd\"")); |
| 123 | + |
| 124 | + tinyxml2::XMLElement* eRoot = xmlDoc.NewElement("fontconfig"); |
| 125 | + xmlDoc.InsertEndChild(eRoot); |
| 126 | + |
| 127 | + auto addRootChildText = [&](const char* name, const std::string& value) |
| 128 | + { |
| 129 | + tinyxml2::XMLElement* elem = xmlDoc.NewElement(name); |
| 130 | + elem->SetText(value.c_str()); |
| 131 | + eRoot->InsertEndChild(elem); |
| 132 | + }; |
| 133 | + |
| 134 | + // Add Android system font directories |
| 135 | + // Note: USER and SYSTEM dirs are handled by ass_set_fonts_dir below |
| 136 | + const std::vector<std::string> fontDirs = { |
| 137 | + "/system/fonts", // AOSP standard |
| 138 | + "/product/fonts", // AOSP vendor-specific |
| 139 | + "/system_ext/fonts" // OEM-specific (may not exist on all devices) |
| 140 | + }; |
| 141 | + |
| 142 | + for (const auto& dir : fontDirs) |
| 143 | + { |
| 144 | + if (XFILE::CDirectory::Exists(dir)) |
| 145 | + addRootChildText("dir", dir); |
| 146 | + } |
| 147 | + |
| 148 | + addRootChildText("cachedir", fontconfigCacheDir); |
| 149 | + |
| 150 | + if (xmlDoc.SaveFile(fontconfigPath)) |
| 151 | + { |
| 152 | + fontconfigConfig = fontconfigPath.c_str(); |
| 153 | + CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Created fontconfig configuration at {}", |
| 154 | + fontconfigPath); |
| 155 | + } |
| 156 | + else |
| 157 | + { |
| 158 | + CLog::LogF(LOGERROR, "Failed to create fontconfig configuration, falling back to " |
| 159 | + "ASS_FONTPROVIDER_AUTODETECT"); |
| 160 | + fontProvider = ASS_FONTPROVIDER_AUTODETECT; |
| 161 | + fontconfigConfig = nullptr; |
| 162 | + } |
| 163 | + } |
| 164 | + else |
| 165 | + { |
| 166 | + fontconfigConfig = fontconfigPath.c_str(); |
| 167 | + } |
| 168 | +#endif |
| 169 | + |
| 170 | + // Set additional fonts directory for libass to scan. This provides font lookup |
| 171 | + // on platforms without a font provider, and supplements fontconfig on platforms that use it. |
99 | 172 | ass_set_fonts_dir(m_library, CSpecialProtocol::TranslatePath(FONT::FONTPATH::USER).c_str()); |
100 | 173 |
|
101 | 174 | // Load additional fonts into Libass memory |
@@ -148,7 +221,7 @@ void CDVDSubtitlesLibass::Configure() |
148 | 221 | } |
149 | 222 |
|
150 | 223 | ass_set_fonts(m_renderer, FONT::FONTPATH::GetSystemFontPath(FONT::FONT_DEFAULT_FILENAME).c_str(), |
151 | | - m_defaultFontFamilyName.c_str(), ASS_FONTPROVIDER_AUTODETECT, nullptr, 1); |
| 224 | + m_defaultFontFamilyName.c_str(), fontProvider, fontconfigConfig, 1); |
152 | 225 |
|
153 | 226 | // Extract font must be set before loading ASS/SSA data, |
154 | 227 | // after that cannot be changed |
|
0 commit comments