44 return wxString::Format(
"%d.%d.%d", FC_MAJOR, FC_MINOR, FC_REVISION );
67 if( aSearchLang.Lower() == aSupportedLang.Lower() )
70 if( aSupportedLang.empty() )
73 if( aSearchLang.empty() )
76 wxArrayString supportedLangBits;
77 wxStringSplit( aSupportedLang.Lower(), supportedLangBits, wxS(
'-' ) );
79 wxArrayString searhcLangBits;
80 wxStringSplit( aSearchLang.Lower(), searhcLangBits, wxS(
'-' ) );
84 if( searhcLangBits.size() == 1 || supportedLangBits.size() == 1 )
86 return searhcLangBits[0] == supportedLangBits[0];
100 if( FcPatternGetString( aPat.
pat, aObj, aIdx, &str ) == FcResultMatch )
101 res = std::string(
reinterpret_cast<char*
>( str ) );
108 std::unordered_map<std::string, std::string>& aFamStringMap )
116 famLang =
getFcString( aPat, FC_FAMILYLANG, langIdx );
118 if( famLang.empty() && langIdx != 0 )
123 aFamStringMap.insert_or_assign( famLang, fam );
125 }
while( langIdx++ < std::numeric_limits<
132 std::unordered_map<std::string, std::string> famStrings;
135 if( famStrings.empty() )
138 for(
auto const& [key, val] : famStrings )
149 return famStrings.begin()->second;
154 int& aFaceIndex,
bool aBold,
bool aItalic )
157 wxString qualifiedFontName = aFontName;
159 wxScopedCharBuffer
const fcBuffer = qualifiedFontName.ToUTF8();
161 FcPattern* pat = FcPatternCreate();
164 FcPatternAddString( pat, FC_STYLE, (
const FcChar8*)
"Bold" );
167 FcPatternAddString( pat, FC_STYLE, (
const FcChar8*)
"Italic" );
169 FcPatternAddString( pat, FC_FAMILY, (FcChar8*) fcBuffer.data() );
171 FcConfigSubstitute(
nullptr, pat, FcMatchPattern );
172 FcDefaultSubstitute( pat );
174 FcResult r = FcResultNoMatch;
175 FcPattern* font = FcFontMatch(
nullptr, pat, &r );
181 FcChar8* file =
nullptr;
183 if( FcPatternGetString( font, FC_FILE, 0, &file ) == FcResultMatch )
185 aFontFile = wxString::FromUTF8( (
char*) file );
189 FcChar8* family =
nullptr;
190 FcChar8* style =
nullptr;
194 std::unordered_map<std::string, std::string> famStrings;
199 if( FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch )
201 FcPatternGetInteger( font, FC_INDEX, 0, &aFaceIndex );
203 fontName = wxString::FromUTF8( (
char*) family );
205 if( FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch )
207 styleStr = wxString::FromUTF8( (
char*) style );
209 if( !styleStr.IsEmpty() )
211 styleStr.Replace( wxS(
" " ), wxS(
":" ) );
212 fontName +=
":" + styleStr;
216 bool has_bold =
false;
217 bool has_ital =
false;
218 wxString lower_style = styleStr.Lower();
220 if( lower_style.Contains( wxS(
"bold" ) )
221 || lower_style.Contains( wxS(
"black" ) )
222 || lower_style.Contains( wxS(
"thick" ) )
223 || lower_style.Contains( wxS(
"dark" ) ) )
228 if( lower_style.Contains( wxS(
"italic" ) )
229 || lower_style.Contains( wxS(
"oblique" ) )
230 || lower_style.Contains( wxS(
"slant" ) ) )
235 for(
auto const& [key, val] : famStrings )
238 searchFont = wxString::FromUTF8( (
char*) val.data() );
240 if( searchFont.Lower().StartsWith( aFontName.Lower() ) )
242 if( ( aBold && !has_bold ) && ( aItalic && !has_ital ) )
244 else if( aBold && !has_bold )
246 else if( aItalic && !has_ital )
248 else if( ( aBold != has_bold ) || ( aItalic != has_ital ) )
259 FcPatternDestroy( font );
263 wxLogWarning(
_(
"Error loading font '%s'." ), qualifiedFontName );
265 wxLogWarning(
_(
"Font '%s' not found; substituting '%s'." ), qualifiedFontName, fontName );
267 FcPatternDestroy( pat );
277 FcPattern* pat = FcPatternCreate();
278 FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_FAMILYLANG, FC_STYLE, FC_LANG, FC_FILE,
279 FC_OUTLINE,
nullptr );
280 FcFontSet* fs = FcFontList(
nullptr, pat, os );
282 for(
int i = 0; fs && i < fs->nfont; ++i )
284 FcPattern* font = fs->fonts[i];
290 if( FcPatternGetString( font, FC_FILE, 0, &file ) == FcResultMatch
291 && FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch
292 && FcPatternGetLangSet( font, FC_LANG, 0, &langSet ) == FcResultMatch
293 && FcPatternGetBool( font, FC_OUTLINE, 0, &outline ) == FcResultMatch )
299 std::string theFamily =
310 FcStrSet* langStrSet = FcLangSetGetLangs( langSet );
311 FcStrList* langStrList = FcStrListCreate( langStrSet );
312 FcChar8* langStr = FcStrListNext( langStrList );
313 bool langSupported =
false;
318 langSupported =
true;
320 else while( langStr )
322 wxString langWxStr(
reinterpret_cast<char *
>( langStr ) );
323 const wxLanguageInfo* langInfo = wxLocale::FindLanguageInfo( langWxStr );
325 if( langInfo && wxLocale::IsAvailable( langInfo->Language ) )
327 langSupported =
true;
332 wxLogTrace(
traceFonts, wxS(
"Font '%s' language '%s' not supported by OS." ),
333 theFamily, langWxStr );
336 langStr = FcStrListNext( langStrList );
339 FcStrListDone( langStrList );
340 FcStrSetDestroy( langStrSet );
346 std::string theFile(
reinterpret_cast<char *
>( file ) );
347 std::string theStyle(
reinterpret_cast<char *
>( style ) );
348 FONTINFO fontInfo( theFile, theStyle, theFamily );
350 if( theFamily.length() > 0 && theFamily.front() ==
'.' )
353 std::map<std::string, FONTINFO>::iterator it =
m_fontInfoCache.find( theFamily );
358 it->second.Children().push_back( fontInfo );
363 FcFontSetDestroy( fs );
368 for(
const std::pair<const std::string, FONTINFO>& entry :
m_fontInfoCache )
369 aFonts.push_back( entry.second.Family() );
void getAllFamilyStrings(FONTCONFIG_PAT &aPat, std::unordered_map< std::string, std::string > &aFamStringMap)
Gets a list of all family name strings maped to lang.
static wxString Version()
std::map< std::string, FONTINFO > m_fontInfoCache
FF_RESULT FindFont(const wxString &aFontName, wxString &aFontFile, int &aFaceIndex, bool aBold, bool aItalic)
Given a fully-qualified font name ("Times:Bold:Italic") find the closest matching font and return its...
void ListFonts(std::vector< std::string > &aFonts, const std::string &aDesiredLang)
List the current available font families.
std::string getFcString(FONTCONFIG_PAT &aPat, const char *aObj, int aIdx)
Wrapper of FcPatternGetString to return a std::string.
std::string getFamilyStringByLang(FONTCONFIG_PAT &APat, const wxString &aDesiredLang)
Gets a family name based on desired language.
bool isLanguageMatch(const wxString &aSearchLang, const wxString &aSupportedLang)
Matches the two rfc 3306 language entries, used for when searching for matching family names.
wxString m_fontCacheLastLang
static FONTCONFIG * g_config
FONTCONFIG * Fontconfig()
const wxChar *const traceFonts
Flag to enable locale debug output.
This file contains miscellaneous commonly used macros and functions.
wxString From_UTF8(const char *cstring)
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
A simple wrapper to avoid exporing fontconfig in the header.
wxLogTrace helper definitions.