Compare commits

..

2 Commits

Author SHA1 Message Date
3c769dc854 feat: Add font tab 2024-06-06 16:32:36 +01:00
de01720d3b fix: Tie dropdown items to button size 2024-06-06 16:21:59 +01:00
14 changed files with 262 additions and 96 deletions

View File

@@ -1 +1 @@
14.1 20240503 0 b3c704a6306027de4aad575c8e394a2d8a1878f9 1 1 2024 14.0 20240413 0 b3c704a6306027de4aad575c8e394a2d8a1878f9 1 1 2024

View File

@@ -22,6 +22,9 @@
#include "safeguards.h" #include "safeguards.h"
static void LoadFontHelper([[maybe_unused]] FontSize fs);
static void TryLoadDefaultTrueTypeFont([[maybe_unused]] FontSize fs);
/** Default heights for the different sizes of fonts. */ /** Default heights for the different sizes of fonts. */
static const int _default_font_height[FS_END] = {10, 6, 18, 10}; static const int _default_font_height[FS_END] = {10, 6, 18, 10};
static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8}; static const int _default_font_ascender[FS_END] = { 8, 5, 15, 8};
@@ -33,7 +36,8 @@ FontCacheSettings _fcsettings;
* @param fs The size of the font. * @param fs The size of the font.
*/ */
FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_default_font_height[fs]), FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_default_font_height[fs]),
ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - _default_font_height[fs]) ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - _default_font_height[fs]),
units_per_em(1)
{ {
assert(this->parent == nullptr || this->fs == this->parent->fs); assert(this->parent == nullptr || this->fs == this->parent->fs);
FontCache::caches[this->fs] = this; FontCache::caches[this->fs] = this;
@@ -98,6 +102,29 @@ bool GetFontAAState(FontSize size, bool check_blitter)
return _fcsettings.global_aa || GetFontCacheSubSetting(size)->aa; return _fcsettings.global_aa || GetFontCacheSubSetting(size)->aa;
} }
void ResizeFont(FontSize font_size, uint size)
{
FontCacheSubSetting *setting = GetFontCacheSubSetting(font_size);
if (setting->size == size) {
return;
}
setting->size = size;
// Default fonts are empty here. We will allow the user to resize the default font:
if (setting->font.empty()){
TryLoadDefaultTrueTypeFont(font_size);
} else {
LoadFontHelper(font_size);
}
LoadStringWidthTable();
UpdateAllVirtCoords();
ReInitAllWindows(true);
if (_save_config) SaveToConfig();
}
void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa) void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa)
{ {
@@ -142,68 +169,66 @@ void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa)
if (_save_config) SaveToConfig(); if (_save_config) SaveToConfig();
} }
void ResizeFont(FontSize fontsize, uint size)
{
FontCacheSubSetting *setting = GetFontCacheSubSetting(fontsize);
SetFont(fontsize, setting->font, size, setting->aa);
}
#ifdef WITH_FREETYPE #ifdef WITH_FREETYPE
extern void LoadFreeTypeFont(FontSize fs); extern void LoadFreeTypeFont(FontSize fs);
extern void LoadFreeTypeFont(FontSize fs, const std::string &file_name, uint size);
extern void UninitFreeType(); extern void UninitFreeType();
#elif defined(_WIN32) #elif defined(_WIN32)
extern void LoadWin32Font(FontSize fs); extern void LoadWin32Font(FontSize fs);
extern void LoadWin32Font(FontSize fs, const std::string &file_name, uint size);
#elif defined(WITH_COCOA) #elif defined(WITH_COCOA)
extern void LoadCoreTextFont(FontSize fs); extern void LoadCoreTextFont(FontSize fs);
extern void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size);
#endif #endif
static void LoadFontHelper([[maybe_unused]] FontSize fs)
#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
/**
* Get name of default font file for a given font size.
* @param fs Font size.
* @return Name of default font file.
*/
static std::string GetDefaultTruetypeFont(FontSize fs)
{ {
#ifdef WITH_FREETYPE
LoadFreeTypeFont(fs);
#elif defined(_WIN32)
LoadWin32Font(fs);
#elif defined(WITH_COCOA)
LoadCoreTextFont(fs);
#endif
}
static void TryLoadDefaultTrueTypeFont([[maybe_unused]] FontSize fs)
{
#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
std::string font_name{};
switch (fs) { switch (fs) {
case FS_NORMAL: return "OpenTTD-Sans.ttf"; case FS_NORMAL:
case FS_SMALL: return "OpenTTD-Small.ttf"; font_name = "OpenTTD-Sans.ttf";
case FS_LARGE: return "OpenTTD-Serif.ttf"; break;
case FS_MONO: return "OpenTTD-Mono.ttf"; case FS_SMALL:
font_name = "OpenTTD-Small.ttf";
break;
case FS_LARGE:
font_name = "OpenTTD-Serif.ttf";
break;
case FS_MONO:
font_name = "OpenTTD-Mono.ttf";
break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
}
#endif /* defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) */
/**
* Get path of default font file for a given font size.
* @param fs Font size.
* @return Full path of default font file.
*/
static std::string GetDefaultTruetypeFontFile([[maybe_unused]] FontSize fs)
{
#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
/* Find font file. */ /* Find font file. */
return FioFindFullPath(BASESET_DIR, GetDefaultTruetypeFont(fs)); std::string full_font = FioFindFullPath(BASESET_DIR, font_name);
#else if (!full_font.empty()) {
return {}; int size = FontCache::GetDefaultFontHeight(fs);
#ifdef WITH_FREETYPE
LoadFreeTypeFont(fs, full_font, size);
#elif defined(_WIN32)
LoadWin32Font(fs, full_font, size);
#elif defined(WITH_COCOA)
LoadCoreTextFont(fs, full_font, size);
#endif
}
#endif /* defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) */ #endif /* defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) */
} }
/**
* Get font to use for a given font size.
* @param fs Font size.
* @return If configured, the font name to use, or the path of the default TrueType font if sprites are not preferred.
*/
std::string GetFontCacheFontName(FontSize fs)
{
const FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
if (!settings->font.empty()) return settings->font;
if (_fcsettings.prefer_sprite) return {};
return GetDefaultTruetypeFontFile(fs);
}
/** /**
* (Re)initialize the font cache related things, i.e. load the non-sprite fonts. * (Re)initialize the font cache related things, i.e. load the non-sprite fonts.
* @param monospace Whether to initialise the monospace or regular fonts. * @param monospace Whether to initialise the monospace or regular fonts.
@@ -218,13 +243,17 @@ void InitFontCache(bool monospace)
FontCache *fc = FontCache::Get(fs); FontCache *fc = FontCache::Get(fs);
if (fc->HasParent()) delete fc; if (fc->HasParent()) delete fc;
if (!_fcsettings.prefer_sprite && GetFontCacheSubSetting(fs)->font.empty()) {
TryLoadDefaultTrueTypeFont(fs);
} else {
#ifdef WITH_FREETYPE #ifdef WITH_FREETYPE
LoadFreeTypeFont(fs); LoadFreeTypeFont(fs);
#elif defined(_WIN32) #elif defined(_WIN32)
LoadWin32Font(fs); LoadWin32Font(fs);
#elif defined(WITH_COCOA) #elif defined(WITH_COCOA)
LoadCoreTextFont(fs); LoadCoreTextFont(fs);
#endif #endif
}
} }
} }

View File

@@ -26,6 +26,7 @@ protected:
int height; ///< The height of the font. int height; ///< The height of the font.
int ascender; ///< The ascender value of the font. int ascender; ///< The ascender value of the font.
int descender; ///< The descender value of the font. int descender; ///< The descender value of the font.
int units_per_em; ///< The units per EM value of the font.
public: public:
FontCache(FontSize fs); FontCache(FontSize fs);
@@ -59,6 +60,12 @@ public:
*/ */
inline int GetDescender() const{ return this->descender; } inline int GetDescender() const{ return this->descender; }
/**
* Get the units per EM value of the font.
* @return The units per EM value of the font.
*/
inline int GetUnitsPerEM() const { return this->units_per_em; }
/** /**
* Get the nominal font size of the font. * Get the nominal font size of the font.
* @return The nominal font size. * @return The nominal font size.
@@ -106,6 +113,14 @@ public:
*/ */
virtual GlyphID MapCharToGlyph(char32_t key, bool fallback = true) = 0; virtual GlyphID MapCharToGlyph(char32_t key, bool fallback = true) = 0;
/**
* Read a font table from the font.
* @param tag The of the table to load.
* @param length The length of the read data.
* @return The loaded table data.
*/
virtual const void *GetFontTable(uint32_t tag, size_t &length) = 0;
/** /**
* Get the native OS font handle, if there is one. * Get the native OS font handle, if there is one.
* @return Opaque OS font handle. * @return Opaque OS font handle.
@@ -225,7 +240,6 @@ inline FontCacheSubSetting *GetFontCacheSubSetting(FontSize fs)
} }
} }
std::string GetFontCacheFontName(FontSize fs);
void InitFontCache(bool monospace); void InitFontCache(bool monospace);
void UninitFontCache(); void UninitFontCache();
void ResizeFont(FontSize font_size, uint32_t size); void ResizeFont(FontSize font_size, uint32_t size);

View File

@@ -33,7 +33,8 @@ class FreeTypeFontCache : public TrueTypeFontCache {
private: private:
FT_Face face; ///< The font face associated with this font. FT_Face face; ///< The font face associated with this font.
void SetFontSize(int pixels); void SetFontSize(FontSize fs, FT_Face face, int pixels);
const void *InternalGetFontTable(uint32_t tag, size_t &length) override;
const Sprite *InternalGetGlyph(GlyphID key, bool aa) override; const Sprite *InternalGetGlyph(GlyphID key, bool aa) override;
public: public:
@@ -59,10 +60,10 @@ FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : Tr
{ {
assert(face != nullptr); assert(face != nullptr);
this->SetFontSize(pixels); this->SetFontSize(fs, face, pixels);
} }
void FreeTypeFontCache::SetFontSize(int pixels) void FreeTypeFontCache::SetFontSize(FontSize, FT_Face, int pixels)
{ {
if (pixels == 0) { if (pixels == 0) {
/* Try to determine a good height based on the minimal height recommended by the font. */ /* Try to determine a good height based on the minimal height recommended by the font. */
@@ -104,6 +105,7 @@ void FreeTypeFontCache::SetFontSize(int pixels)
} }
if (err == FT_Err_Ok) { if (err == FT_Err_Ok) {
this->units_per_em = this->face->units_per_EM;
this->ascender = this->face->size->metrics.ascender >> 6; this->ascender = this->face->size->metrics.ascender >> 6;
this->descender = this->face->size->metrics.descender >> 6; this->descender = this->face->size->metrics.descender >> 6;
this->height = this->ascender - this->descender; this->height = this->ascender - this->descender;
@@ -160,8 +162,7 @@ void LoadFreeTypeFont(FontSize fs)
{ {
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs); FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
std::string font = GetFontCacheFontName(fs); if (settings->font.empty()) return;
if (font.empty()) return;
if (_library == nullptr) { if (_library == nullptr) {
if (FT_Init_FreeType(&_library) != FT_Err_Ok) { if (FT_Init_FreeType(&_library) != FT_Err_Ok) {
@@ -172,7 +173,7 @@ void LoadFreeTypeFont(FontSize fs)
Debug(fontcache, 2, "Initialized"); Debug(fontcache, 2, "Initialized");
} }
const char *font_name = font.c_str(); const char *font_name = settings->font.c_str();
FT_Face face = nullptr; FT_Face face = nullptr;
/* If font is an absolute path to a ttf, try loading that first. */ /* If font is an absolute path to a ttf, try loading that first. */
@@ -201,6 +202,34 @@ void LoadFreeTypeFont(FontSize fs)
} }
} }
/**
* 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 LoadFreeTypeFont(FontSize fs, const std::string &file_name, uint size)
{
if (_library == nullptr) {
if (FT_Init_FreeType(&_library) != FT_Err_Ok) {
ShowInfo("Unable to initialize FreeType, using sprite fonts instead");
return;
}
Debug(fontcache, 2, "Initialized");
}
FT_Face face = nullptr;
int32_t index = 0;
FT_Error error = FT_New_Face(_library, file_name.c_str(), index, &face);
if (error == FT_Err_Ok) {
LoadFont(fs, face, file_name.c_str(), size);
} else {
FT_Done_Face(face);
}
}
/** /**
* Free everything that was allocated for this font cache. * Free everything that was allocated for this font cache.
*/ */
@@ -217,7 +246,7 @@ FreeTypeFontCache::~FreeTypeFontCache()
void FreeTypeFontCache::ClearFontCache() void FreeTypeFontCache::ClearFontCache()
{ {
/* Font scaling might have changed, determine font size anew if it was automatically selected. */ /* Font scaling might have changed, determine font size anew if it was automatically selected. */
if (this->face != nullptr) this->SetFontSize(this->req_size); if (this->face != nullptr) this->SetFontSize(this->fs, this->face, this->req_size);
this->TrueTypeFontCache::ClearFontCache(); this->TrueTypeFontCache::ClearFontCache();
} }
@@ -296,6 +325,22 @@ GlyphID FreeTypeFontCache::MapCharToGlyph(char32_t key, bool allow_fallback)
return glyph; return glyph;
} }
const void *FreeTypeFontCache::InternalGetFontTable(uint32_t tag, size_t &length)
{
FT_ULong len = 0;
FT_Byte *result = nullptr;
FT_Load_Sfnt_Table(this->face, tag, 0, nullptr, &len);
if (len > 0) {
result = MallocT<FT_Byte>(len);
FT_Load_Sfnt_Table(this->face, tag, 0, result, &len);
}
length = len;
return result;
}
/** /**
* Free everything allocated w.r.t. freetype. * Free everything allocated w.r.t. freetype.
*/ */

View File

@@ -30,6 +30,7 @@ public:
uint GetGlyphWidth(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override;
bool GetDrawGlyphShadow() override; bool GetDrawGlyphShadow() override;
GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { assert(IsPrintable(key)); return SPRITE_GLYPH | key; } GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { assert(IsPrintable(key)); return SPRITE_GLYPH | key; }
const void *GetFontTable(uint32_t, size_t &length) override { length = 0; return nullptr; }
std::string GetFontName() override { return "sprite"; } std::string GetFontName() override { return "sprite"; }
bool IsBuiltInFont() override { return true; } bool IsBuiltInFont() override { return true; }
}; };

View File

@@ -33,6 +33,10 @@ TrueTypeFontCache::~TrueTypeFontCache()
{ {
/* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */ /* Virtual functions get called statically in destructors, so make it explicit to remove any confusion. */
this->TrueTypeFontCache::ClearFontCache(); this->TrueTypeFontCache::ClearFontCache();
for (auto &iter : this->font_tables) {
free(iter.second.second);
}
} }
/** /**
@@ -160,3 +164,17 @@ const Sprite *TrueTypeFontCache::GetGlyph(GlyphID key)
return this->InternalGetGlyph(key, GetFontAAState(this->fs)); return this->InternalGetGlyph(key, GetFontAAState(this->fs));
} }
const void *TrueTypeFontCache::GetFontTable(uint32_t tag, size_t &length)
{
const auto iter = this->font_tables.find(tag);
if (iter != this->font_tables.end()) {
length = iter->second.first;
return iter->second.second;
}
const void *result = this->InternalGetFontTable(tag, length);
this->font_tables[tag] = std::pair<size_t, const void *>(length, result);
return result;
}

View File

@@ -27,6 +27,9 @@ protected:
int req_size; ///< Requested font size. int req_size; ///< Requested font size.
int used_size; ///< Used font size. int used_size; ///< Used font size.
using FontTable = std::map<uint32_t, std::pair<size_t, const void *>>; ///< Table with font table cache
FontTable font_tables; ///< Cached font tables.
/** Container for information about a glyph. */ /** Container for information about a glyph. */
struct GlyphEntry { struct GlyphEntry {
Sprite *sprite; ///< The loaded sprite. Sprite *sprite; ///< The loaded sprite.
@@ -52,6 +55,7 @@ protected:
GlyphEntry *GetGlyphPtr(GlyphID key); GlyphEntry *GetGlyphPtr(GlyphID key);
void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false); void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false);
virtual const void *InternalGetFontTable(uint32_t tag, size_t &length) = 0;
virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0; virtual const Sprite *InternalGetGlyph(GlyphID key, bool aa) = 0;
public: public:
@@ -61,6 +65,7 @@ public:
void SetUnicodeGlyph(char32_t key, SpriteID sprite) override { this->parent->SetUnicodeGlyph(key, sprite); } void SetUnicodeGlyph(char32_t key, SpriteID sprite) override { this->parent->SetUnicodeGlyph(key, sprite); }
void InitializeUnicodeGlyphMap() override { this->parent->InitializeUnicodeGlyphMap(); } void InitializeUnicodeGlyphMap() override { this->parent->InitializeUnicodeGlyphMap(); }
const Sprite *GetGlyph(GlyphID key) override; const Sprite *GetGlyph(GlyphID key) override;
const void *GetFontTable(uint32_t tag, size_t &length) override;
void ClearFontCache() override; void ClearFontCache() override;
uint GetGlyphWidth(GlyphID key) override; uint GetGlyphWidth(GlyphID key) override;
bool GetDrawGlyphShadow() override; bool GetDrawGlyphShadow() override;

View File

@@ -166,6 +166,7 @@ void CoreTextFontCache::SetFontSize(int pixels)
/* Query the font metrics we needed. We generally round all values up to /* Query the font metrics we needed. We generally round all values up to
* make sure we don't inadvertently cut off a row or column of pixels, * make sure we don't inadvertently cut off a row or column of pixels,
* except when determining glyph to glyph advances. */ * except when determining glyph to glyph advances. */
this->units_per_em = CTFontGetUnitsPerEm(this->font.get());
this->ascender = (int)std::ceil(CTFontGetAscent(this->font.get())); this->ascender = (int)std::ceil(CTFontGetAscent(this->font.get()));
this->descender = -(int)std::ceil(CTFontGetDescent(this->font.get())); this->descender = -(int)std::ceil(CTFontGetDescent(this->font.get()));
this->height = this->ascender - this->descender; this->height = this->ascender - this->descender;
@@ -204,6 +205,18 @@ GlyphID CoreTextFontCache::MapCharToGlyph(char32_t key, bool allow_fallback)
return 0; return 0;
} }
const void *CoreTextFontCache::InternalGetFontTable(uint32_t tag, size_t &length)
{
CFAutoRelease<CFDataRef> data(CTFontCopyTable(this->font.get(), (CTFontTableTag)tag, kCTFontTableOptionNoOptions));
if (!data) return nullptr;
length = CFDataGetLength(data.get());
auto buf = MallocT<UInt8>(length);
CFDataGetBytes(data.get(), CFRangeMake(0, (CFIndex)length), buf);
return buf;
}
const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa) const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
{ {
/* Get glyph size. */ /* Get glyph size. */
@@ -328,8 +341,7 @@ void LoadCoreTextFont(FontSize fs)
{ {
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs); FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
std::string font = GetFontCacheFontName(fs); if (settings->font.empty()) return;
if (font.empty()) return;
CFAutoRelease<CTFontDescriptorRef> font_ref; CFAutoRelease<CTFontDescriptorRef> font_ref;
@@ -340,12 +352,12 @@ void LoadCoreTextFont(FontSize fs)
if (!font_ref && MacOSVersionIsAtLeast(10, 6, 0)) { if (!font_ref && MacOSVersionIsAtLeast(10, 6, 0)) {
/* Might be a font file name, try load it. */ /* Might be a font file name, try load it. */
font_ref.reset(LoadFontFromFile(font)); font_ref.reset(LoadFontFromFile(settings->font));
if (!font_ref) ShowInfo("Unable to load file '{}' for {} font, using default OS font selection instead", font, FontSizeToName(fs)); if (!font_ref) ShowInfo("Unable to load file '{}' for {} font, using default OS font selection instead", settings->font, FontSizeToName(fs));
} }
if (!font_ref) { if (!font_ref) {
CFAutoRelease<CFStringRef> name(CFStringCreateWithCString(kCFAllocatorDefault, font.c_str(), kCFStringEncodingUTF8)); CFAutoRelease<CFStringRef> name(CFStringCreateWithCString(kCFAllocatorDefault, settings->font.c_str(), kCFStringEncodingUTF8));
/* Simply creating the font using CTFontCreateWithNameAndSize will *always* return /* Simply creating the font using CTFontCreateWithNameAndSize will *always* return
* something, no matter the name. As such, we can't use it to check for existence. * something, no matter the name. As such, we can't use it to check for existence.
@@ -363,9 +375,23 @@ void LoadCoreTextFont(FontSize fs)
} }
if (!font_ref) { if (!font_ref) {
ShowInfo("Unable to use '{}' for {} font, using sprite font instead", font, FontSizeToName(fs)); ShowInfo("Unable to use '{}' for {} font, using sprite font instead", settings->font, FontSizeToName(fs));
return; return;
} }
new CoreTextFontCache(fs, std::move(font_ref), settings->size); 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);
}
}

View File

@@ -23,6 +23,7 @@ class CoreTextFontCache : public TrueTypeFontCache {
void SetFontSize(int pixels); void SetFontSize(int pixels);
const Sprite *InternalGetGlyph(GlyphID key, bool use_aa) override; const Sprite *InternalGetGlyph(GlyphID key, bool use_aa) override;
const void *InternalGetFontTable(uint32_t tag, size_t &length) override;
public: public:
CoreTextFontCache(FontSize fs, CFAutoRelease<CTFontDescriptorRef> &&font, int pixels); CoreTextFontCache(FontSize fs, CFAutoRelease<CTFontDescriptorRef> &&font, int pixels);
~CoreTextFontCache() {} ~CoreTextFontCache() {}
@@ -35,5 +36,6 @@ public:
}; };
void LoadCoreTextFont(FontSize fs); void LoadCoreTextFont(FontSize fs);
void LoadCoreTextFont(FontSize fs, const std::string &file_name, uint size);
#endif /* FONT_OSX_H */ #endif /* FONT_OSX_H */

View File

@@ -182,6 +182,7 @@ void Win32FontCache::SetFontSize(int pixels)
POUTLINETEXTMETRIC otm = (POUTLINETEXTMETRIC)new BYTE[otmSize]; POUTLINETEXTMETRIC otm = (POUTLINETEXTMETRIC)new BYTE[otmSize];
GetOutlineTextMetrics(this->dc, otmSize, otm); GetOutlineTextMetrics(this->dc, otmSize, otm);
this->units_per_em = otm->otmEMSquare;
this->ascender = otm->otmTextMetrics.tmAscent; this->ascender = otm->otmTextMetrics.tmAscent;
this->descender = otm->otmTextMetrics.tmDescent; this->descender = otm->otmTextMetrics.tmDescent;
this->height = this->ascender + this->descender; this->height = this->ascender + this->descender;
@@ -298,6 +299,20 @@ void Win32FontCache::ClearFontCache()
return allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END ? this->parent->MapCharToGlyph(key) : 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)
{
DWORD len = GetFontData(this->dc, tag, 0, nullptr, 0);
void *result = nullptr;
if (len != GDI_ERROR && len > 0) {
result = MallocT<BYTE>(len);
GetFontData(this->dc, tag, 0, result, len);
}
length = len;
return result;
}
static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont) static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont)
{ {
@@ -369,10 +384,9 @@ void LoadWin32Font(FontSize fs)
{ {
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs); FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
std::string font = GetFontCacheFontName(fs); if (settings->font.empty()) return;
if (font.empty()) return;
const char *font_name = font.c_str(); const char *font_name = settings->font.c_str();
LOGFONT logfont; LOGFONT logfont;
MemSetT(&logfont, 0); MemSetT(&logfont, 0);
logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH; logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH;
@@ -384,8 +398,8 @@ void LoadWin32Font(FontSize fs)
logfont = *(const LOGFONT *)settings->os_handle; logfont = *(const LOGFONT *)settings->os_handle;
} else if (strchr(font_name, '.') != nullptr) { } else if (strchr(font_name, '.') != nullptr) {
/* Might be a font file name, try load it. */ /* Might be a font file name, try load it. */
if (!TryLoadFontFromFile(font, logfont)) { if (!TryLoadFontFromFile(settings->font, logfont)) {
ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font, FontSizeToName(fs)); ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font_name, FontSizeToName(fs));
} }
} }
@@ -396,3 +410,23 @@ void LoadWin32Font(FontSize fs)
LoadWin32Font(fs, logfont, settings->size, font_name); 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());
}
}

View File

@@ -28,6 +28,7 @@ private:
void SetFontSize(int pixels); void SetFontSize(int pixels);
protected: protected:
const void *InternalGetFontTable(uint32_t tag, size_t &length) override;
const Sprite *InternalGetGlyph(GlyphID key, bool aa) override; const Sprite *InternalGetGlyph(GlyphID key, bool aa) override;
public: public:
@@ -40,5 +41,6 @@ public:
}; };
void LoadWin32Font(FontSize fs); void LoadWin32Font(FontSize fs);
void LoadWin32Font(FontSize fs, const std::string &file_name, uint size);
#endif /* FONT_WIN32_H */ #endif /* FONT_WIN32_H */

View File

@@ -11,7 +11,6 @@
#include "currency.h" #include "currency.h"
#include "error.h" #include "error.h"
#include "settings_gui.h" #include "settings_gui.h"
#include "string_type.h"
#include "textbuf_gui.h" #include "textbuf_gui.h"
#include "command_func.h" #include "command_func.h"
#include "network/network.h" #include "network/network.h"
@@ -358,8 +357,18 @@ std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
return std::make_unique<NWidgetSocialPlugins>(); return std::make_unique<NWidgetSocialPlugins>();
} }
static inline FontCacheSubSetting *getSafeFontCacheSub(FontSize fs) {
FontCache *fc = FontCache::Get(fs);
FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
/* Make sure all non sprite fonts are loaded. */
if (!setting->font.empty() && !fc->HasParent()) {
InitFontCache(fs == FS_MONO);
fc = FontCache::Get(fs);
}
return setting;
}
struct GameOptionsWindow : Window { struct GameOptionsWindow : Window {
int query_widget;
GameSettings *opt; GameSettings *opt;
bool reload; bool reload;
int gui_scale; int gui_scale;
@@ -374,7 +383,7 @@ struct GameOptionsWindow : Window {
this->gui_scale = _gui_scale; this->gui_scale = _gui_scale;
this->button_ratio = _button_ratio; this->button_ratio = _button_ratio;
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){
FontCacheSubSetting *fc = GetFontCacheSubSetting(fs); FontCacheSubSetting *fc = getSafeFontCacheSub(fs);
font_sizes[fs] = fc->size; font_sizes[fs] = fc->size;
} }
@@ -824,26 +833,13 @@ struct GameOptionsWindow : Window {
case WID_GO_MONO_FONT_L: case WID_GO_MONO_FONT_L:
case WID_GO_MONO_FONT_R: { case WID_GO_MONO_FONT_R: {
int index = widget - WID_GO_NORMAL_FONT_L; int index = widget - WID_GO_NORMAL_FONT_L;
FontSize fs = static_cast<FontSize>(Clamp((widget - WID_GO_NORMAL_FONT_L) / 2, FS_BEGIN, FS_END)); FontSize fs = static_cast<FontSize>(Clamp((widget - WID_GO_NORMAL_FONT_L) / 2, FS_BEGIN, FS_END));
if (index % 2 == 0) { if (index % 2 == 0) {
this->font_sizes[fs] = Clamp(this->font_sizes[fs] - 1, 0, 200); this->font_sizes[fs] = Clamp(this->font_sizes[fs] - 1, 0, 200);
} else { } else {
this->font_sizes[fs] = Clamp(this->font_sizes[fs] + 1, 0, 200); this->font_sizes[fs] = Clamp(this->font_sizes[fs] + 1, 0, 200);
} }
break;
}
case WID_GO_NORMAL_FONT_VALUE:
case WID_GO_SMALL_FONT_VALUE:
case WID_GO_LARGE_FONT_VALUE:
case WID_GO_MONO_FONT_VALUE: {
int index = Clamp(widget - WID_GO_NORMAL_FONT_VALUE, FS_BEGIN, FS_END);
this->query_widget = widget;
FontSize fs = static_cast<FontSize>(index);
SetDParam(0, this->font_sizes[fs]);
ShowQueryString(STR_JUST_INT, STR_GAME_OPTIONS_FONT_NORMAL + index, 3, this, CS_NUMERAL, QSF_NONE);
break;
} }
case WID_GO_MOUSE_CURSOR: case WID_GO_MOUSE_CURSOR:
@@ -963,15 +959,6 @@ struct GameOptionsWindow : Window {
} }
} }
void OnQueryTextFinished(char *str) override
{
if (str == nullptr) return;
int index = Clamp(this->query_widget - WID_GO_NORMAL_FONT_VALUE, FS_BEGIN, FS_END);
this->font_sizes[index] = Clamp(atoi(str), 0, 200);
}
bool anySizeSettingChanged() bool anySizeSettingChanged()
{ {
if (this->gui_scale != _gui_scale || this->button_ratio != _button_ratio) { if (this->gui_scale != _gui_scale || this->button_ratio != _button_ratio) {
@@ -979,7 +966,7 @@ struct GameOptionsWindow : Window {
} }
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){
FontCacheSubSetting *fc = GetFontCacheSubSetting(fs); FontCacheSubSetting *fc = getSafeFontCacheSub(fs);
if (this->font_sizes[fs] != fc->size) if (this->font_sizes[fs] != fc->size)
return true; return true;
} }
@@ -994,7 +981,7 @@ struct GameOptionsWindow : Window {
_button_ratio_cfg = this->button_ratio; _button_ratio_cfg = this->button_ratio;
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){ for (FontSize fs = FS_BEGIN; fs < FS_END; fs++){
FontCacheSubSetting *fc = GetFontCacheSubSetting(fs); FontCacheSubSetting *fc = getSafeFontCacheSub(fs);
if (this->font_sizes[fs] != fc->size) { if (this->font_sizes[fs] != fc->size) {
ResizeFont(fs, this->font_sizes[fs]); ResizeFont(fs, this->font_sizes[fs]);
return; return;

View File

@@ -30,6 +30,7 @@ public:
uint GetGlyphWidth(GlyphID) override { return this->height / 2; } uint GetGlyphWidth(GlyphID) override { return this->height / 2; }
bool GetDrawGlyphShadow() override { return false; } bool GetDrawGlyphShadow() override { return false; }
GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { return key; } GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { return key; }
const void *GetFontTable(uint32_t, size_t &length) override { length = 0; return nullptr; }
std::string GetFontName() override { return "mock"; } std::string GetFontName() override { return "mock"; }
bool IsBuiltInFont() override { return true; } bool IsBuiltInFont() override { return true; }

View File

@@ -525,7 +525,9 @@ bool VideoDriver_SDL::PollEvent()
} }
if (_cursor.UpdateCursorPosition(x, y)) { if (_cursor.UpdateCursorPosition(x, y)) {
#ifndef __ANDROID__ // No mouse warping on Android, mouse strictly follows finger
SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y);
#endif
} }
HandleMouseEvents(); HandleMouseEvents();
break; break;