diff --git a/CMakeLists.txt b/CMakeLists.txt index b88bc3f3c1..cb16a3f4df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,8 +86,8 @@ else (WIN32) PKG_CHECK_MODULES(SPEEX REQUIRED speexdsp) endif (WIN32) -# Include libdl for dlopen if (UNIX) + # Include libdl for dlopen set(DLLIB dl) endif (UNIX) @@ -113,6 +113,13 @@ if (APPLE) TARGET_LINK_LIBRARIES(${PROJECT} ${ICONV_LIBRARIES}) endif (APPLE) +if (UNIX AND NOT APPLE) + # FontConfig for TrueType fonts. + PKG_CHECK_MODULES(FONTCONFIG REQUIRED fontconfig) + INCLUDE_DIRECTORIES(${FONTCONFIG_INCLUDE_DIRS}) + TARGET_LINK_LIBRARIES(${PROJECT} ${FONTCONFIG_LIBRARIES}) +endif (UNIX AND NOT APPLE) + # Handle creating the rct2 text and data files on OS X and Linux # See details in src/openrct2.c:openrct2_setup_rct2_segment for how the values # were derived. diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 9e01dd71f8..b5d1f453c7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -3,6 +3,7 @@ - Feature: Add displaying of frames per second (FPS). - Feature: Changing the number of trains no longer requires retesting. - Feature: Add SI units as a new measurement system for distance / speed. +- Feature: Update alternative font selection mechanism for all platforms. - Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug) - Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day diff --git a/scripts/linux/install.sh b/scripts/linux/install.sh index e56c80384e..466a7d44e0 100755 --- a/scripts/linux/install.sh +++ b/scripts/linux/install.sh @@ -171,7 +171,7 @@ elif [[ $(uname) == "Linux" ]]; then "linux") sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install --no-install-recommends -y --force-yes cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386 libcurl4-openssl-dev:i386 libcrypto++-dev:i386 clang + sudo apt-get install --no-install-recommends -y --force-yes cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386 libcurl4-openssl-dev:i386 libcrypto++-dev:i386 clang libfontconfig1-dev:i386 libfreetype6-dev:i386 libpng-dev:i386 download https://launchpad.net/ubuntu/+archive/primary/+files/libjansson4_2.7-1ubuntu1_i386.deb libjansson4_2.7-1ubuntu1_i386.deb download https://launchpad.net/ubuntu/+archive/primary/+files/libjansson-dev_2.7-1ubuntu1_i386.deb libjansson-dev_2.7-1ubuntu1_i386.deb sudo dpkg -i libjansson4_2.7-1ubuntu1_i386.deb diff --git a/src/drawing/font.h b/src/drawing/font.h index de7abc298b..e680bb4322 100644 --- a/src/drawing/font.h +++ b/src/drawing/font.h @@ -23,6 +23,7 @@ enum { typedef struct { const utf8 *filename; + const utf8 *font_name; int ptSize; int offset_x; int offset_y; diff --git a/src/drawing/string.c b/src/drawing/string.c index f4241b4b4e..f12f0af0e0 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -888,8 +888,11 @@ bool ttf_initialise() for (int i = 0; i < 4; i++) { TTFFontDescriptor *fontDesc = &(gCurrentTTFFontSet->size[i]); - utf8 fontPath[MAX_PATH] = "C:\\Windows\\Fonts\\"; - strcat(fontPath, fontDesc->filename); + utf8 fontPath[MAX_PATH]; + if (!platform_get_font_path(fontDesc, fontPath)) { + log_error("Unable to load font '%s'", fontDesc->font_name); + return false; + } fontDesc->font = TTF_OpenFont(fontPath, fontDesc->ptSize); if (fontDesc->font == NULL) { diff --git a/src/localisation/language.cpp b/src/localisation/language.cpp index 33adeb6e83..f9d36eb779 100644 --- a/src/localisation/language.cpp +++ b/src/localisation/language.cpp @@ -48,31 +48,31 @@ enum { }; static TTFFontSetDescriptor TTFFontMingLiu = {{ - { "msjh.ttc", 9, -1, -3, 6, nullptr }, - { "mingliu.ttc", 11, 1, 1, 12, nullptr }, - { "mingliu.ttc", 12, 1, 0, 12, nullptr }, - { "mingliu.ttc", 13, 1, 0, 20, nullptr }, + { "msjh.ttc", "JhengHei", 9, -1, -3, 6, nullptr }, + { "mingliu.ttc", "MingLiU", 11, 1, 1, 12, nullptr }, + { "mingliu.ttc", "MingLiU", 12, 1, 0, 12, nullptr }, + { "mingliu.ttc", "MingLiU", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontSimSun = {{ - { "msyh.ttc", 9, -1, -3, 6, nullptr }, - { "simsun.ttc", 11, 1, -1, 14, nullptr }, - { "simsun.ttc", 12, 1, -2, 14, nullptr }, - { "simsun.ttc", 13, 1, 0, 20, nullptr }, + { "msyh.ttc", "YaHei", 9, -1, -3, 6, nullptr }, + { "simsun.ttc", "SimSun", 11, 1, -1, 14, nullptr }, + { "simsun.ttc", "SimSun", 12, 1, -2, 14, nullptr }, + { "simsun.ttc", "SimSun", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontGulim = {{ - { "gulim.ttc", 11, 1, 0, 15, nullptr }, - { "gulim.ttc", 12, 1, 0, 17, nullptr }, - { "gulim.ttc", 12, 1, 0, 17, nullptr }, - { "gulim.ttc", 13, 1, 0, 20, nullptr }, + { "gulim.ttc", "Gulim", 11, 1, 0, 15, nullptr }, + { "gulim.ttc", "Gulim", 12, 1, 0, 17, nullptr }, + { "gulim.ttc", "Gulim", 12, 1, 0, 17, nullptr }, + { "gulim.ttc", "Gulim", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontArial = {{ - { "arial.ttf", 8, 0, -1, 6, nullptr }, - { "arial.ttf", 10, 0, -1, 12, nullptr }, - { "arial.ttf", 11, 0, -1, 12, nullptr }, - { "arial.ttf", 12, 0, -1, 20, nullptr }, + { "arial.ttf", "Arial", 8, 0, -1, 6, nullptr }, + { "arial.ttf", "Arial", 10, 0, -1, 12, nullptr }, + { "arial.ttf", "Arial", 11, 0, -1, 12, nullptr }, + { "arial.ttf", "Arial", 12, 0, -1, 20, nullptr }, }}; const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = { @@ -173,10 +173,18 @@ int language_open(int id) ttf_dispose(); gUseTrueTypeFont = true; gCurrentTTFFontSet = LanguagesDescriptors[id].font; - if (!ttf_initialise()) { - log_warning("Unable to initialise TrueType fonts."); + bool font_initialised = ttf_initialise(); - // Fall back to sprite font + // Have we tried Arial yet? + if (!font_initialised && gCurrentTTFFontSet != &TTFFontArial) { + log_warning("Unable to initialise prefered TrueType font -- falling back to Arial."); + gCurrentTTFFontSet = &TTFFontArial; + font_initialised = ttf_initialise(); + } + + // Fall back to sprite font. + if (!font_initialised) { + log_warning("Falling back to sprite font."); gUseTrueTypeFont = false; gCurrentTTFFontSet = nullptr; return 0; diff --git a/src/platform/linux.c b/src/platform/linux.c index 3dc44da9b7..22e3245fcb 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -24,6 +24,7 @@ #include #include #include "../util/util.h" +#include "fontconfig/fontconfig.h" // See http://syprog.blogspot.ru/2011/12/listing-loaded-shared-objects-in-linux.html struct lmap { @@ -163,4 +164,46 @@ int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 return 0; } +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ + assert(buffer != NULL); + assert(font != NULL); + + log_verbose("Looking for font %s with FontConfig.", font->font_name); + FcConfig* config = FcInitLoadConfigAndFonts(); + if (!config) + { + log_error("Failed to initialize FontConfig library"); + FcFini(); + return false; + } + FcPattern* pat = FcNameParse((const FcChar8*) font->font_name); + + FcConfigSubstitute(config, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + + bool found = false; + FcResult result = FcResultNoMatch; + FcPattern* match = FcFontMatch(config, pat, &result); + + if (match) + { + FcChar8* filename = NULL; + if (FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) + { + found = true; + safe_strncpy(buffer, (utf8*) filename, MAX_PATH); + log_verbose("FontConfig provided font %s", filename); + } + FcPatternDestroy(match); + } else { + log_warning("Failed to find required font."); + } + + FcPatternDestroy(pat); + FcConfigDestroy(config); + FcFini(); + return found; +} + #endif diff --git a/src/platform/osx.m b/src/platform/osx.m index 1052cad4b8..784a3d7aab 100644 --- a/src/platform/osx.m +++ b/src/platform/osx.m @@ -172,4 +172,20 @@ int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 } } +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ + @autoreleasepool + { + CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize((CFStringRef)[NSString stringWithUTF8String:font->font_name], 0.0); + CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute); + if (url) { + NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]]; + strcpy(buffer, fontPath.UTF8String); + return true; + } else { + return false; + } + } +} + #endif diff --git a/src/platform/platform.h b/src/platform/platform.h index 0d65b6c566..c9e3eb23ad 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -28,6 +28,7 @@ #include #include "../common.h" +#include "../drawing/font.h" #ifndef MAX_PATH #define MAX_PATH 260 @@ -161,6 +162,7 @@ uint8 platform_get_locale_currency(); uint16 platform_get_locale_language(); uint8 platform_get_locale_measurement_format(); uint8 platform_get_locale_temperature_format(); +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer); bool platform_check_steam_overlay_attached(); diff --git a/src/platform/windows.c b/src/platform/windows.c index d07f765fcd..3a447571d3 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -897,4 +897,36 @@ void platform_get_exe_path(utf8 *outPath) _wfullpath(exePath, tempPath, MAX_PATH); WideCharToMultiByte(CP_UTF8, 0, exePath, countof(exePath), outPath, MAX_PATH, NULL, NULL); } + +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ +#ifndef __MINGW32__ + wchar_t *fontFolder; + if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Fonts, 0, NULL, &fontFolder))) + { + // Convert wchar to utf8, then copy the font folder path to the buffer. + utf8 *outPathTemp = widechar_to_utf8(fontFolder); + strcpy(buffer, outPathTemp); + free(outPathTemp); + + CoTaskMemFree(fontFolder); + + // Append the requested font's file name. + const char separator[2] = { platform_get_path_separator(), 0 }; + strcat(buffer, separator); + strcat(buffer, font->filename); + return true; + } + else + { + return false; + } +#else + log_warning("MINGW-compatibility hack: falling back to C:\\Windows\\Fonts"); + strcat(buffer, "C:\\Windows\\Fonts\\"); + strcat(buffer, font->filename); + return true; +#endif +} + #endif