Merge branch 'master' into jgrpp
# Conflicts: # media/baseset/CMakeLists.txt # src/build_vehicle_gui.cpp # src/console.cpp # src/debug.cpp # src/fontcache/freetypefontcache.cpp # src/network/network.cpp # src/openttd.cpp # src/os/macosx/font_osx.cpp # src/os/windows/font_win32.cpp # src/settings_gui.cpp # src/video/sdl2_v.cpp # src/widgets/settings_widget.h # src/window_gui.h
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../debug_fmt.h"
|
||||
#include "font_osx.h"
|
||||
#include "../../core/math_func.hpp"
|
||||
#include "../../blitter/factory.hpp"
|
||||
@@ -182,14 +183,10 @@ void CoreTextFontCache::SetFontSize(int pixels)
|
||||
DEBUG(fontcache, 2, "Loaded font '%s' with size %d", this->font_name.c_str(), pixels);
|
||||
}
|
||||
|
||||
GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key)
|
||||
GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key, bool allow_fallback)
|
||||
{
|
||||
assert(IsPrintable(key));
|
||||
|
||||
if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
|
||||
return this->parent->MapCharToGlyph(key);
|
||||
}
|
||||
|
||||
/* Convert characters outside of the Basic Multilingual Plane into surrogate pairs. */
|
||||
UniChar chars[2];
|
||||
if (key >= 0x010000U) {
|
||||
@@ -204,6 +201,10 @@ GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key)
|
||||
return glyph[0];
|
||||
}
|
||||
|
||||
if (allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
|
||||
return this->parent->MapCharToGlyph(key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -300,6 +301,40 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
|
||||
return new_glyph.sprite;
|
||||
}
|
||||
|
||||
static CTFontDescriptorRef LoadFontFromFile(const std::string &font_name)
|
||||
{
|
||||
if (!MacOSVersionIsAtLeast(10, 6, 0)) return nullptr;
|
||||
|
||||
/* Might be a font file name, try load it. Direct font loading is
|
||||
* only supported starting on OSX 10.6. */
|
||||
CFAutoRelease<CFStringRef> path;
|
||||
|
||||
/* See if this is an absolute path. */
|
||||
if (FileExists(font_name)) {
|
||||
path.reset(CFStringCreateWithCString(kCFAllocatorDefault, font_name.c_str(), kCFStringEncodingUTF8));
|
||||
} else {
|
||||
/* Scan the search-paths to see if it can be found. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, font_name);
|
||||
if (!full_font.empty()) {
|
||||
path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8));
|
||||
}
|
||||
}
|
||||
|
||||
if (path) {
|
||||
/* Try getting a font descriptor to see if the system can use it. */
|
||||
CFAutoRelease<CFURLRef> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(), kCFURLPOSIXPathStyle, false));
|
||||
CFAutoRelease<CFArrayRef> descs(CTFontManagerCreateFontDescriptorsFromURL(url.get()));
|
||||
|
||||
if (descs && CFArrayGetCount(descs.get()) > 0) {
|
||||
CTFontDescriptorRef font_ref = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0);
|
||||
CFRetain(font_ref);
|
||||
return font_ref;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the TrueType font.
|
||||
* If a CoreText font description is present, e.g. from the automatic font
|
||||
@@ -320,33 +355,9 @@ void LoadCoreTextFont(FontSize fs)
|
||||
}
|
||||
|
||||
if (!font_ref && MacOSVersionIsAtLeast(10, 6, 0)) {
|
||||
/* Might be a font file name, try load it. Direct font loading is
|
||||
* only supported starting on OSX 10.6. */
|
||||
CFAutoRelease<CFStringRef> path;
|
||||
|
||||
/* See if this is an absolute path. */
|
||||
if (FileExists(settings->font)) {
|
||||
path.reset(CFStringCreateWithCString(kCFAllocatorDefault, settings->font.c_str(), kCFStringEncodingUTF8));
|
||||
} else {
|
||||
/* Scan the search-paths to see if it can be found. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, settings->font);
|
||||
if (!full_font.empty()) {
|
||||
path.reset(CFStringCreateWithCString(kCFAllocatorDefault, full_font.c_str(), kCFStringEncodingUTF8));
|
||||
}
|
||||
}
|
||||
|
||||
if (path) {
|
||||
/* Try getting a font descriptor to see if the system can use it. */
|
||||
CFAutoRelease<CFURLRef> url(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path.get(), kCFURLPOSIXPathStyle, false));
|
||||
CFAutoRelease<CFArrayRef> descs(CTFontManagerCreateFontDescriptorsFromURL(url.get()));
|
||||
|
||||
if (descs && CFArrayGetCount(descs.get()) > 0) {
|
||||
font_ref.reset((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), 0));
|
||||
CFRetain(font_ref.get());
|
||||
} else {
|
||||
ShowInfoF("Unable to load file '%s' for %s font, using default OS font selection instead", settings->font.c_str(), FontSizeToName(fs));
|
||||
}
|
||||
}
|
||||
/* Might be a font file name, try load it. */
|
||||
font_ref.reset(LoadFontFromFile(settings->font));
|
||||
if (!font_ref) ShowInfo("Unable to load file '{}' for {} font, using default OS font selection instead", settings->font, FontSizeToName(fs));
|
||||
}
|
||||
|
||||
if (!font_ref) {
|
||||
@@ -374,3 +385,17 @@ void LoadCoreTextFont(FontSize fs)
|
||||
|
||||
new CoreTextFontCache(fs, std::move(font_ref), settings->size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a TrueType font from a file.
|
||||
* @param fs The font size to load.
|
||||
* @param file_name Path to the font file.
|
||||
* @param size Requested font size.
|
||||
*/
|
||||
void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size)
|
||||
{
|
||||
CFAutoRelease<CTFontDescriptorRef> font_ref{LoadFontFromFile(file_name)};
|
||||
if (font_ref) {
|
||||
new CoreTextFontCache(fs, std::move(font_ref), size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,13 @@ public:
|
||||
~CoreTextFontCache() {}
|
||||
|
||||
void ClearFontCache() override;
|
||||
GlyphID MapCharToGlyph(char32_t key) override;
|
||||
GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override;
|
||||
std::string GetFontName() override { return font_name; }
|
||||
bool IsBuiltInFont() override { return false; }
|
||||
const void *GetOSHandle() override { return font.get(); }
|
||||
};
|
||||
|
||||
void LoadCoreTextFont(FontSize fs);
|
||||
void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size);
|
||||
|
||||
#endif /* FONT_OSX_H */
|
||||
|
||||
@@ -170,6 +170,9 @@ static CTRunDelegateCallbacks _sprite_font_callback = {
|
||||
CFAutoRelease<CFStringRef> base(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull));
|
||||
CFAttributedStringReplaceString(str.get(), CFRangeMake(0, 0), base.get());
|
||||
|
||||
const UniChar replacment_char = 0xFFFC;
|
||||
CFAutoRelease<CFStringRef> replacment_str(CFStringCreateWithCharacters(kCFAllocatorDefault, &replacment_char, 1));
|
||||
|
||||
/* Apply font and colour ranges to our string. This is important to make sure
|
||||
* that we get proper glyph boundaries on style changes. */
|
||||
int last = 0;
|
||||
@@ -191,10 +194,12 @@ static CTRunDelegateCallbacks _sprite_font_callback = {
|
||||
CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color);
|
||||
CGColorRelease(color);
|
||||
|
||||
/* Install a size callback for our special sprite glyphs. */
|
||||
/* Install a size callback for our special private-use sprite glyphs in case the font does not provide them. */
|
||||
for (ssize_t c = last; c < i.first; c++) {
|
||||
if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END) {
|
||||
if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END && i.second->fc->MapCharToGlyph(buff[c], false) == 0) {
|
||||
CFAutoRelease<CTRunDelegateRef> del(CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24))));
|
||||
/* According to the offical documentation, if a run delegate is used, the char should always be 0xFFFC. */
|
||||
CFAttributedStringReplaceString(str.get(), CFRangeMake(c, 1), replacment_str.get());
|
||||
CFAttributedStringSetAttribute(str.get(), CFRangeMake(c, 1), kCTRunDelegateAttributeName, del.get());
|
||||
}
|
||||
}
|
||||
@@ -244,7 +249,8 @@ CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font
|
||||
CGGlyph gl[this->glyphs.size()];
|
||||
CTRunGetGlyphs(run, CFRangeMake(0, 0), gl);
|
||||
for (size_t i = 0; i < this->glyphs.size(); i++) {
|
||||
if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END) {
|
||||
if (buff[this->glyph_to_char[i]] >= SCC_SPRITE_START && buff[this->glyph_to_char[i]] <= SCC_SPRITE_END && (gl[i] == 0 || gl[i] == 3)) {
|
||||
/* A glyph of 0 indidicates not found, while apparently 3 is what char 0xFFFC maps to. */
|
||||
this->glyphs[i] = font->fc->MapCharToGlyph(buff[this->glyph_to_char[i]]);
|
||||
this->positions[i * 2 + 0] = pts[i].x;
|
||||
this->positions[i * 2 + 1] = (font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(font->fc->GetSize()))) / 2; // Align sprite font to centre
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../debug.h"
|
||||
#include "../../debug_fmt.h"
|
||||
#include "../../blitter/factory.hpp"
|
||||
#include "../../core/alloc_func.hpp"
|
||||
#include "../../core/math_func.hpp"
|
||||
@@ -279,14 +280,10 @@ void Win32FontCache::ClearFontCache()
|
||||
return new_glyph.sprite;
|
||||
}
|
||||
|
||||
/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key)
|
||||
/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key, bool allow_fallback)
|
||||
{
|
||||
assert(IsPrintable(key));
|
||||
|
||||
if (key >= SCC_SPRITE_START && key <= SCC_SPRITE_END) {
|
||||
return this->parent->MapCharToGlyph(key);
|
||||
}
|
||||
|
||||
/* Convert characters outside of the BMP into surrogate pairs. */
|
||||
WCHAR chars[2];
|
||||
if (key >= 0x010000U) {
|
||||
@@ -299,7 +296,8 @@ void Win32FontCache::ClearFontCache()
|
||||
WORD glyphs[2] = { 0, 0 };
|
||||
GetGlyphIndicesW(this->dc, chars, key >= 0x010000U ? 2 : 1, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
|
||||
|
||||
return glyphs[0] != 0xFFFF ? glyphs[0] : 0;
|
||||
if (glyphs[0] != 0xFFFF) return glyphs[0];
|
||||
return allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END ? this->parent->MapCharToGlyph(key) : 0;
|
||||
}
|
||||
|
||||
/* virtual */ const void *Win32FontCache::InternalGetFontTable(uint32_t tag, size_t &length)
|
||||
@@ -317,6 +315,66 @@ void Win32FontCache::ClearFontCache()
|
||||
}
|
||||
|
||||
|
||||
static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont)
|
||||
{
|
||||
wchar_t fontPath[MAX_PATH] = {};
|
||||
|
||||
/* See if this is an absolute path. */
|
||||
if (FileExists(font_name)) {
|
||||
convert_to_fs(font_name, fontPath, lengthof(fontPath));
|
||||
} else {
|
||||
/* Scan the search-paths to see if it can be found. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, font_name);
|
||||
if (!full_font.empty()) {
|
||||
convert_to_fs(font_name, fontPath, lengthof(fontPath));
|
||||
}
|
||||
}
|
||||
|
||||
if (fontPath[0] != 0) {
|
||||
if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) {
|
||||
/* Try a nice little undocumented function first for getting the internal font name.
|
||||
* Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */
|
||||
static LibraryLoader _gdi32("gdi32.dll");
|
||||
typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD);
|
||||
static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetFunction("GetFontResourceInfoW");
|
||||
|
||||
if (GetFontResourceInfo != nullptr) {
|
||||
/* Try to query an array of LOGFONTs that describe the file. */
|
||||
DWORD len = 0;
|
||||
if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) {
|
||||
LOGFONT *buf = (LOGFONT *)new byte[len];
|
||||
if (GetFontResourceInfo(fontPath, &len, buf, 2)) {
|
||||
logfont = *buf; // Just use first entry.
|
||||
}
|
||||
delete[](byte *)buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* No dice yet. Use the file name as the font face name, hoping it matches. */
|
||||
if (logfont.lfFaceName[0] == 0) {
|
||||
wchar_t fname[_MAX_FNAME];
|
||||
_wsplitpath(fontPath, nullptr, nullptr, fname, nullptr);
|
||||
|
||||
wcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE);
|
||||
logfont.lfWeight = strcasestr(font_name.c_str(), " bold") != nullptr || strcasestr(font_name.c_str(), "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return logfont.lfFaceName[0] != 0;
|
||||
}
|
||||
|
||||
static void LoadWin32Font(FontSize fs, const LOGFONT &logfont, uint size, const char *font_name)
|
||||
{
|
||||
HFONT font = CreateFontIndirect(&logfont);
|
||||
if (font == nullptr) {
|
||||
ShowInfo("Unable to use '{}' for {} font, Win32 reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), GetLastError());
|
||||
return;
|
||||
}
|
||||
DeleteObject(font);
|
||||
|
||||
new Win32FontCache(fs, logfont, size);
|
||||
}
|
||||
/**
|
||||
* Loads the GDI font.
|
||||
* If a GDI font description is present, e.g. from the automatic font
|
||||
@@ -341,50 +399,8 @@ void LoadWin32Font(FontSize fs)
|
||||
logfont = *(const LOGFONT *)settings->os_handle;
|
||||
} else if (strchr(font_name, '.') != nullptr) {
|
||||
/* Might be a font file name, try load it. */
|
||||
|
||||
wchar_t fontPath[MAX_PATH] = {};
|
||||
|
||||
/* See if this is an absolute path. */
|
||||
if (FileExists(settings->font)) {
|
||||
convert_to_fs(font_name, fontPath, lengthof(fontPath));
|
||||
} else {
|
||||
/* Scan the search-paths to see if it can be found. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, font_name);
|
||||
if (!full_font.empty()) {
|
||||
convert_to_fs(font_name, fontPath, lengthof(fontPath));
|
||||
}
|
||||
}
|
||||
|
||||
if (fontPath[0] != 0) {
|
||||
if (AddFontResourceEx(fontPath, FR_PRIVATE, 0) != 0) {
|
||||
/* Try a nice little undocumented function first for getting the internal font name.
|
||||
* Some documentation is found at: http://www.undocprint.org/winspool/getfontresourceinfo */
|
||||
static LibraryLoader _gdi32("gdi32.dll");
|
||||
typedef BOOL(WINAPI *PFNGETFONTRESOURCEINFO)(LPCTSTR, LPDWORD, LPVOID, DWORD);
|
||||
static PFNGETFONTRESOURCEINFO GetFontResourceInfo = _gdi32.GetFunction("GetFontResourceInfoW");
|
||||
|
||||
if (GetFontResourceInfo != nullptr) {
|
||||
/* Try to query an array of LOGFONTs that describe the file. */
|
||||
DWORD len = 0;
|
||||
if (GetFontResourceInfo(fontPath, &len, nullptr, 2) && len >= sizeof(LOGFONT)) {
|
||||
LOGFONT *buf = (LOGFONT *)AllocaM(byte, len);
|
||||
if (GetFontResourceInfo(fontPath, &len, buf, 2)) {
|
||||
logfont = *buf; // Just use first entry.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No dice yet. Use the file name as the font face name, hoping it matches. */
|
||||
if (logfont.lfFaceName[0] == 0) {
|
||||
wchar_t fname[_MAX_FNAME];
|
||||
_wsplitpath(fontPath, nullptr, nullptr, fname, nullptr);
|
||||
|
||||
wcsncpy_s(logfont.lfFaceName, lengthof(logfont.lfFaceName), fname, _TRUNCATE);
|
||||
logfont.lfWeight = strcasestr(font_name, " bold") != nullptr || strcasestr(font_name, "-bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts.
|
||||
}
|
||||
} else {
|
||||
ShowInfoF("Unable to load file '%s' for %s font, using default windows font selection instead", font_name, FontSizeToName(fs));
|
||||
}
|
||||
if (!TryLoadFontFromFile(settings->font, logfont)) {
|
||||
ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font_name, FontSizeToName(fs));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,12 +409,25 @@ void LoadWin32Font(FontSize fs)
|
||||
convert_to_fs(font_name, logfont.lfFaceName, lengthof(logfont.lfFaceName));
|
||||
}
|
||||
|
||||
HFONT font = CreateFontIndirect(&logfont);
|
||||
if (font == nullptr) {
|
||||
ShowInfoF("Unable to use '%s' for %s font, Win32 reported error 0x%lX, using sprite font instead", font_name, FontSizeToName(fs), GetLastError());
|
||||
return;
|
||||
}
|
||||
DeleteObject(font);
|
||||
|
||||
new Win32FontCache(fs, logfont, settings->size);
|
||||
LoadWin32Font(fs, logfont, settings->size, font_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a TrueType font from a file.
|
||||
* @param fs The font size to load.
|
||||
* @param file_name Path to the font file.
|
||||
* @param size Requested font size.
|
||||
*/
|
||||
void LoadWin32Font(FontSize fs, const std::string &file_name, uint size)
|
||||
{
|
||||
LOGFONT logfont;
|
||||
MemSetT(&logfont, 0);
|
||||
logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH;
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
|
||||
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
|
||||
if (TryLoadFontFromFile(file_name, logfont)) {
|
||||
LoadWin32Font(fs, logfont, size, file_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,12 @@ public:
|
||||
Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels);
|
||||
~Win32FontCache();
|
||||
void ClearFontCache() override;
|
||||
GlyphID MapCharToGlyph(char32_t key) override;
|
||||
GlyphID MapCharToGlyph(char32_t key, bool allow_fallback = true) override;
|
||||
std::string GetFontName() override { return this->fontname; }
|
||||
const void *GetOSHandle() override { return &this->logfont; }
|
||||
};
|
||||
|
||||
void LoadWin32Font(FontSize fs);
|
||||
void LoadWin32Font(FontSize fs, const std::string &file_name, uint size);
|
||||
|
||||
#endif /* FONT_WIN32_H */
|
||||
|
||||
@@ -195,9 +195,11 @@ static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *b
|
||||
for (int i = 0; i < range.len; i++) {
|
||||
if (buff[range.pos + i] >= SCC_SPRITE_START && buff[range.pos + i] <= SCC_SPRITE_END) {
|
||||
auto pos = range.char_to_glyph[i];
|
||||
range.ft_glyphs[pos] = range.font->fc->MapCharToGlyph(buff[range.pos + i]);
|
||||
range.offsets[pos].dv = (range.font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(range.font->fc->GetSize()))) / 2; // Align sprite font to centre
|
||||
range.advances[pos] = range.font->fc->GetGlyphWidth(range.ft_glyphs[pos]);
|
||||
if (range.ft_glyphs[pos] == 0) { // Font doesn't have our special glyph, so remap.
|
||||
range.ft_glyphs[pos] = range.font->fc->MapCharToGlyph(buff[range.pos + i]);
|
||||
range.offsets[pos].dv = (range.font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(range.font->fc->GetSize()))) / 2; // Align sprite font to centre
|
||||
range.advances[pos] = range.font->fc->GetGlyphWidth(range.ft_glyphs[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user