20 extern FT_Library _library;
 
   50 const char *GetShortPath(
const TCHAR *long_path)
 
   52   static char short_path[MAX_PATH];
 
   54   WCHAR short_path_w[MAX_PATH];
 
   55   GetShortPathName(long_path, short_path_w, 
lengthof(short_path_w));
 
   56   WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, 
lengthof(short_path), NULL, NULL);
 
   59   GetShortPathName(long_path, short_path, 
lengthof(short_path));
 
   72 #define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" 
   73 #define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts" 
   76   FT_Error err = FT_Err_Cannot_Open_Resource;
 
   79   TCHAR vbuffer[MAX_PATH], dbuffer[256];
 
   81   const char *font_path;
 
   88   ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey);
 
   89   if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey);
 
   91   if (ret != ERROR_SUCCESS) {
 
   92     DEBUG(freetype, 0, 
"Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
 
   97   TCHAR *font_namep = _tcsdup(
OTTD2FS(font_name));
 
   99   for (index = 0;; index++) {
 
  104     ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, NULL, NULL, (byte*)dbuffer, &dbuflen);
 
  105     if (ret != ERROR_SUCCESS) 
goto registry_no_font_found;
 
  116     s = _tcschr(vbuffer, _T(
'('));
 
  117     if (s != NULL) s[-1] = 
'\0';
 
  119     if (_tcschr(vbuffer, _T(
'&')) == NULL) {
 
  120       if (_tcsicmp(vbuffer, font_namep) == 0) 
break;
 
  122       if (_tcsstr(vbuffer, font_namep) != NULL) 
break;
 
  126   if (!SUCCEEDED(
OTTDSHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) {
 
  127     DEBUG(freetype, 0, 
"SHGetFolderPath cannot return fonts directory");
 
  135   path_len = _tcslen(vbuffer) + _tcslen(dbuffer) + 2; 
 
  136   pathbuf = 
AllocaM(TCHAR, path_len);
 
  137   _sntprintf(pathbuf, path_len, _T(
"%s\\%s"), vbuffer, dbuffer);
 
  140   font_path = GetShortPath(pathbuf);
 
  144     err = FT_New_Face(_library, font_path, index, face);
 
  145     if (err != FT_Err_Ok) 
break;
 
  147     if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) 
break;
 
  149     if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) 
break;
 
  150     err = FT_Err_Cannot_Open_Resource;
 
  152   } 
while ((FT_Long)++index != (*face)->num_faces);
 
  156 registry_no_font_found:
 
  175 static const char *GetEnglishFontName(
const ENUMLOGFONTEX *logfont)
 
  177   static char font_name[MAX_PATH];
 
  178   const char *ret_font_name = NULL;
 
  184   uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset;
 
  186   HFONT font = CreateFontIndirect(&logfont->elfLogFont);
 
  187   if (font == NULL) 
goto err1;
 
  190   oldfont = SelectObject(dc, font);
 
  191   dw = GetFontData(dc, 
'eman', 0, NULL, 0);
 
  192   if (dw == GDI_ERROR) 
goto err2;
 
  194   buf = MallocT<byte>(dw);
 
  195   dw = GetFontData(dc, 
'eman', 0, buf, dw);
 
  196   if (dw == GDI_ERROR) 
goto err3;
 
  198   format = buf[pos++] << 8;
 
  199   format += buf[pos++];
 
  201   count = buf[pos++] << 8;
 
  203   stringOffset = buf[pos++] << 8;
 
  204   stringOffset += buf[pos++];
 
  205   for (uint i = 0; i < count; i++) {
 
  206     platformId = buf[pos++] << 8;
 
  207     platformId += buf[pos++];
 
  208     encodingId = buf[pos++] << 8;
 
  209     encodingId += buf[pos++];
 
  210     languageId = buf[pos++] << 8;
 
  211     languageId += buf[pos++];
 
  212     nameId = buf[pos++] << 8;
 
  213     nameId += buf[pos++];
 
  218     length = buf[pos++] << 8;
 
  219     length += buf[pos++];
 
  220     offset = buf[pos++] << 8;
 
  221     offset += buf[pos++];
 
  224     length = 
min(length, MAX_PATH - 1);
 
  225     for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j];
 
  226     font_name[length] = 
'\0';
 
  228     if ((platformId == 1 && languageId == 0) ||      
 
  229         (platformId == 3 && languageId == 0x0409)) { 
 
  230       ret_font_name = font_name;
 
  238   SelectObject(dc, oldfont);
 
  242   return ret_font_name == NULL ? WIDE_TO_MB((
const TCHAR*)logfont->elfFullName) : ret_font_name;
 
  252   FontList() : fonts(NULL), items(0), capacity(0) { };
 
  255     if (this->fonts == NULL) 
return;
 
  257     for (uint i = 0; i < this->items; i++) {
 
  258       free(this->fonts[i]);
 
  264   bool Add(
const TCHAR *font) {
 
  265     for (uint i = 0; i < this->items; i++) {
 
  266       if (_tcscmp(this->fonts[i], font) == 0) 
return false;
 
  269     if (this->items == this->capacity) {
 
  270       this->capacity += 10;
 
  271       this->fonts = 
ReallocT(this->fonts, this->capacity);
 
  274     this->fonts[this->items++] = _tcsdup(font);
 
  282   LOCALESIGNATURE  locale;
 
  287 static int CALLBACK EnumFontCallback(
const ENUMLOGFONTEX *logfont, 
const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam)
 
  289   EFCParam *info = (EFCParam *)lParam;
 
  292   if (!info->fonts.Add((
const TCHAR*)logfont->elfFullName)) 
return 1;
 
  294   if (!(type & TRUETYPE_FONTTYPE)) 
return 1;
 
  296   if (logfont->elfLogFont.lfCharSet == SYMBOL_CHARSET) 
return 1;
 
  298   if (info->callback->Monospace() && (logfont->elfLogFont.lfPitchAndFamily & (FF_MODERN | FIXED_PITCH)) != (FF_MODERN | FIXED_PITCH)) 
return 1;
 
  301   if ((metric->ntmFontSig.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (metric->ntmFontSig.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) {
 
  304     memset(&fs, 0, 
sizeof(fs));
 
  305     HFONT font = CreateFontIndirect(&logfont->elfLogFont);
 
  307       HDC dc = GetDC(NULL);
 
  308       HGDIOBJ oldfont = SelectObject(dc, font);
 
  309       GetTextCharsetInfo(dc, &fs, 0);
 
  310       SelectObject(dc, oldfont);
 
  314     if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) 
return 1;
 
  317   char font_name[MAX_PATH];
 
  321   const char *english_name = GetEnglishFontName(logfont);
 
  322   strecpy(font_name + strlen(font_name) + 1, english_name, 
lastof(font_name));
 
  325   bool ft_init = _library != NULL;
 
  329   if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && 
GetFontByFaceName(font_name, &face) == FT_Err_Ok) {
 
  335     FT_Done_FreeType(_library);
 
  339   if (!found) 
return 1;
 
  341   info->callback->SetFontNames(info->settings, font_name);
 
  342   if (info->callback->FindMissingGlyphs(NULL)) 
return 1;
 
  343   DEBUG(freetype, 1, 
"Fallback font: %s (%s)", font_name, english_name);
 
  349   DEBUG(freetype, 1, 
"Trying fallback fonts");
 
  351   if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, 
sizeof(langInfo.locale) / 
sizeof(TCHAR)) == 0) {
 
  353     DEBUG(freetype, 1, 
"Can't get locale info for fallback font (langid=0x%x)", winlangid);
 
  356   langInfo.settings = settings;
 
  357   langInfo.callback = callback;
 
  361   font.lfCharSet = DEFAULT_CHARSET;
 
  362   font.lfFaceName[0] = 
'\0';
 
  363   font.lfPitchAndFamily = 0;
 
  365   HDC dc = GetDC(NULL);
 
  366   int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0);
 
  371 #elif defined(__APPLE__)  
  382   FT_Error err = FT_Err_Cannot_Open_Resource;
 
  385   CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8);
 
  386   ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault);
 
  388   if (font == kInvalidFont) 
return err;
 
  392   OSStatus os_err = -1;
 
  393 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 
  395     os_err = ATSFontGetFileReference(font, &ref);
 
  399 #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !defined(__LP64__) 
  401 #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) 
  402   #define ATSFSSpec FSSpec 
  405     os_err = ATSFontGetFileSpecification(font, (ATSFSSpec *)&spec);
 
  406     if (os_err == noErr) os_err = FSpMakeFSRef(&spec, &ref);
 
  410   if (os_err == noErr) {
 
  413     if (FSRefMakePath(&ref, file_path, 
sizeof(file_path)) == noErr) {
 
  414       DEBUG(freetype, 3, 
"Font path for %s: %s", font_name, file_path);
 
  415       err = FT_New_Face(_library, (
const char *)file_path, 0, face);
 
  426 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 
  431     if (strcmp(language_isocode, 
"zh_TW") == 0) {
 
  434     } 
else if (strcmp(language_isocode, 
"zh_CN") == 0) {
 
  440       char *sep = strchr(lang, 
'_');
 
  441       if (sep != NULL) *sep = 
'\0';
 
  445     CFStringRef lang_codes[2];
 
  446     lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8);
 
  447     lang_codes[1] = CFSTR(
"en");
 
  448     CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (
const void **)lang_codes, 
lengthof(lang_codes), &kCFTypeArrayCallBacks);
 
  449     CFDictionaryRef lang_attribs = CFDictionaryCreate(kCFAllocatorDefault, (
const void**)&kCTFontLanguagesAttribute, (
const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 
  450     CTFontDescriptorRef lang_desc = CTFontDescriptorCreateWithAttributes(lang_attribs);
 
  452     CFRelease(lang_attribs);
 
  453     CFRelease(lang_codes[0]);
 
  456     CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (
const void **)&kCTFontLanguagesAttribute, 1, &kCFTypeSetCallBacks);
 
  457     CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(lang_desc, mandatory_attribs);
 
  458     CFRelease(mandatory_attribs);
 
  459     CFRelease(lang_desc);
 
  461     for (CFIndex i = 0; descs != NULL && i < CFArrayGetCount(descs); i++) {
 
  462       CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i);
 
  465       CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute);
 
  466       CTFontSymbolicTraits symbolic_traits;
 
  467       CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
 
  471       if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) 
continue;
 
  473       if (symbolic_traits & kCTFontBoldTrait) 
continue;
 
  475       if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->
Monospace()) 
continue;
 
  479       CFStringRef font_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute);
 
  480       CFStringGetCString(font_name, name, 
lengthof(name), kCFStringEncodingUTF8);
 
  481       CFRelease(font_name);
 
  485       if (name[0] == 
'.' || strncmp(name, 
"LastResort", 10) == 0) 
continue;
 
  490         DEBUG(freetype, 2, 
"CT-Font for %s: %s", language_isocode, name);
 
  495     if (descs != NULL) CFRelease(descs);
 
  503     ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsDefaultScope, &itr);
 
  504     while (!result && ATSFontIteratorNext(itr, &font) == noErr) {
 
  507       CFStringRef font_name;
 
  508       ATSFontGetName(font, kATSOptionFlagsDefault, &font_name);
 
  509       CFStringGetCString(font_name, name, 
lengthof(name), kCFStringEncodingUTF8);
 
  511       bool monospace = IsMonospaceFont(font_name);
 
  512       CFRelease(font_name);
 
  515       if (monospace != callback->
Monospace()) 
continue;
 
  518       if (strstr(name, 
"Italic") != NULL || strstr(name, 
"Bold")) 
continue;
 
  521       if (name[0] == 
'.' || strncmp(name, 
"Apple Symbols", 13) == 0 || strncmp(name, 
"LastResort", 10) == 0) 
continue;
 
  526         DEBUG(freetype, 2, 
"ATS-Font for %s: %s", language_isocode, name);
 
  531     ATSFontIteratorRelease(&itr);
 
  545 #elif defined(WITH_FONTCONFIG)  
  547 #include <fontconfig/fontconfig.h> 
  556   FT_Error err = FT_Err_Cannot_Open_Resource;
 
  559     ShowInfoF(
"Unable to load font configuration");
 
  569     font_family = 
stredup(font_name);
 
  570     font_style = strchr(font_family, 
',');
 
  571     if (font_style != NULL) {
 
  572       font_style[0] = 
'\0';
 
  574       while (*font_style == 
' ' || *font_style == 
'\t') font_style++;
 
  578     pat = FcNameParse((FcChar8*)font_family);
 
  579     if (font_style != NULL) FcPatternAddString(pat, FC_STYLE, (FcChar8*)font_style);
 
  580     FcConfigSubstitute(0, pat, FcMatchPattern);
 
  581     FcDefaultSubstitute(pat);
 
  582     fs = FcFontSetCreate();
 
  583     match = FcFontMatch(0, pat, &result);
 
  585     if (fs != NULL && match != NULL) {
 
  590       FcFontSetAdd(fs, match);
 
  592       for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) {
 
  594         if (FcPatternGetString(fs->fonts[i], FC_FILE,   0, &file)   == FcResultMatch &&
 
  595             FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch &&
 
  596             FcPatternGetString(fs->fonts[i], FC_STYLE,  0, &style)  == FcResultMatch) {
 
  599           if (font_style != NULL && strcasecmp(font_style, (
char*)style) != 0) 
continue;
 
  604           if (strcasecmp(font_family, (
char*)family) == 0) {
 
  605             err = FT_New_Face(_library, (
char *)file, 0, face);
 
  612     FcPatternDestroy(pat);
 
  613     FcFontSetDestroy(fs);
 
  622   if (!FcInit()) 
return false;
 
  631   char *split = strchr(lang, 
'_');
 
  632   if (split != NULL) *split = 
'\0';
 
  635   FcPattern *pat = FcNameParse((FcChar8*)lang);
 
  637   FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, NULL);
 
  639   FcFontSet *fs = FcFontList(NULL, pat, os);
 
  642   FcObjectSetDestroy(os);
 
  643   FcPatternDestroy(pat);
 
  646     int best_weight = -1;
 
  647     const char *best_font = NULL;
 
  649     for (
int i = 0; i < fs->nfont; i++) {
 
  650       FcPattern *font = fs->fonts[i];
 
  652       FcChar8 *file = NULL;
 
  653       FcResult res = FcPatternGetString(font, FC_FILE, 0, &file);
 
  654       if (res != FcResultMatch || file == NULL) {
 
  660       FcPatternGetInteger(font, FC_SPACING, 0, &value);
 
  661       if (callback->
Monospace() != (value == FC_MONO) && value != FC_DUAL) 
continue;
 
  664       FcPatternGetInteger(font, FC_SLANT, 0, &value);
 
  665       if (value != 0) 
continue;
 
  668       FcPatternGetInteger(font, FC_WEIGHT, 0, &value);
 
  669       if (value <= best_weight) 
continue;
 
  674       DEBUG(freetype, 1, 
"Font \"%s\" misses%s glyphs", file, missing ? 
"" : 
" no");
 
  678         best_font   = (
const char *)file;
 
  682     if (best_font != NULL) {
 
  689     FcFontSetDestroy(fs);
 
  697 FT_Error 
GetFontByFaceName(
const char *font_name, FT_Face *face) {
return FT_Err_Cannot_Open_Resource;}