Skip to content

Commit 66abe46

Browse files
authored
Merge pull request xbmc#27517 from naseef/android-fontconfig
[Android][libass] Enable fontconfig for libass to support all language scripts in subtitles
2 parents bc1ce97 + 2bc861f commit 66abe46

File tree

1 file changed

+78
-5
lines changed

1 file changed

+78
-5
lines changed

xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitlesLibass.cpp

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "utils/FontUtils.h"
2222
#include "utils/StringUtils.h"
2323
#include "utils/URIUtils.h"
24+
#include "utils/XBMCTinyXML2.h"
2425
#include "utils/log.h"
2526

2627
#include <algorithm>
@@ -92,10 +93,82 @@ void CDVDSubtitlesLibass::Configure()
9293
ass_set_margins(m_renderer, 0, 0, 0, 0);
9394
ass_set_use_margins(m_renderer, 0);
9495

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.
99172
ass_set_fonts_dir(m_library, CSpecialProtocol::TranslatePath(FONT::FONTPATH::USER).c_str());
100173

101174
// Load additional fonts into Libass memory
@@ -148,7 +221,7 @@ void CDVDSubtitlesLibass::Configure()
148221
}
149222

150223
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);
152225

153226
// Extract font must be set before loading ASS/SSA data,
154227
// after that cannot be changed

0 commit comments

Comments
 (0)