mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
4 Commits
29c854a9f6
...
1a8a4c5782
Author | SHA1 | Date |
---|---|---|
|
1a8a4c5782 | |
|
ae917cb8c6 | |
|
d5e0fa7a73 | |
|
b32f46f36e |
|
@ -187,7 +187,6 @@ add_files(
|
|||
fios_gui.cpp
|
||||
fontcache.cpp
|
||||
fontcache.h
|
||||
fontdetection.h
|
||||
framerate_gui.cpp
|
||||
framerate_type.h
|
||||
gamelog.cpp
|
||||
|
|
|
@ -2369,7 +2369,7 @@ static bool ConFont(std::span<std::string_view> argv)
|
|||
FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
|
||||
/* Make sure all non sprite fonts are loaded. */
|
||||
if (!setting->font.empty() && !fc->HasParent()) {
|
||||
InitFontCache(fs);
|
||||
FontCache::LoadFontCaches(fs);
|
||||
fc = FontCache::Get(fs);
|
||||
}
|
||||
IConsolePrint(CC_DEFAULT, "{} font:", FontSizeToName(fs));
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "fontcache.h"
|
||||
#include "fontdetection.h"
|
||||
#include "blitter/factory.hpp"
|
||||
#include "gfx_layout.h"
|
||||
#include "fontcache/spritefontcache.h"
|
||||
#include "openttd.h"
|
||||
#include "settings_func.h"
|
||||
#include "strings_func.h"
|
||||
|
@ -30,22 +28,38 @@
|
|||
FontCacheSettings _fcsettings;
|
||||
|
||||
/**
|
||||
* Create a new font cache.
|
||||
* @param fs The size of the font.
|
||||
* Try loading a font with any fontcache factory.
|
||||
* @param fs Font size to load.
|
||||
* @param fonttype Font type requested.
|
||||
* @return FontCache of the font if loaded, or nullptr.
|
||||
*/
|
||||
FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs)
|
||||
/* static */ std::unique_ptr<FontCache> FontProviderManager::LoadFont(FontSize fs, FontType fonttype)
|
||||
{
|
||||
assert(this->parent == nullptr || this->fs == this->parent->fs);
|
||||
FontCache::caches[this->fs] = this;
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
for (auto &provider : FontProviderManager::GetProviders()) {
|
||||
auto fc = provider->LoadFont(fs, fonttype);
|
||||
if (fc != nullptr) return fc;
|
||||
}
|
||||
|
||||
/** Clean everything up. */
|
||||
FontCache::~FontCache()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* We would like to have a fallback font as the current one
|
||||
* doesn't contain all characters we need.
|
||||
* This function must set all fonts of settings.
|
||||
* @param settings the settings to overwrite the fontname of.
|
||||
* @param language_isocode the language, e.g. en_GB.
|
||||
* @param callback The function to call to check for missing glyphs.
|
||||
* @return true if a font has been set, false otherwise.
|
||||
*/
|
||||
/* static */ bool FontProviderManager::FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback)
|
||||
{
|
||||
assert(this->parent == nullptr || this->fs == this->parent->fs);
|
||||
FontCache::caches[this->fs] = this->parent;
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
for (auto &provider : FontProviderManager::GetProviders()) {
|
||||
if (provider->FindFallbackFont(settings, language_isocode, callback)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int FontCache::GetDefaultFontHeight(FontSize fs)
|
||||
|
@ -80,12 +94,16 @@ int GetCharacterHeight(FontSize size)
|
|||
}
|
||||
|
||||
|
||||
/* static */ FontCache *FontCache::caches[FS_END];
|
||||
/* static */ std::array<std::unique_ptr<FontCache>, FS_END> FontCache::caches{};
|
||||
|
||||
/**
|
||||
* Initialise font caches with the base sprite font cache for all sizes.
|
||||
*/
|
||||
/* static */ void FontCache::InitializeFontCaches()
|
||||
{
|
||||
for (FontSize fs = FS_BEGIN; fs != FS_END; fs++) {
|
||||
if (FontCache::caches[fs] == nullptr) new SpriteFontCache(fs); /* FontCache inserts itself into to the cache. */
|
||||
if (FontCache::Get(fs) != nullptr) continue;
|
||||
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::Sprite));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +144,7 @@ void SetFont(FontSize fontsize, const std::string &font, uint size)
|
|||
CheckForMissingGlyphs();
|
||||
_fcsettings = std::move(backup);
|
||||
} else {
|
||||
InitFontCache(fontsize);
|
||||
FontCache::LoadFontCaches(fontsize);
|
||||
}
|
||||
|
||||
LoadStringWidthTable(fontsize);
|
||||
|
@ -136,15 +154,6 @@ void SetFont(FontSize fontsize, const std::string &font, uint size)
|
|||
if (_save_config) SaveToConfig();
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
extern void LoadFreeTypeFont(FontSize fs);
|
||||
extern void UninitFreeType();
|
||||
#elif defined(_WIN32)
|
||||
extern void LoadWin32Font(FontSize fs);
|
||||
#elif defined(WITH_COCOA)
|
||||
extern void LoadCoreTextFont(FontSize fs);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Test if a font setting uses the default font.
|
||||
* @return true iff the font is not configured and no fallback font data is present.
|
||||
|
@ -211,43 +220,55 @@ std::string GetFontCacheFontName(FontSize fs)
|
|||
return GetDefaultTruetypeFontFile(fs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a FontCache for its font size.
|
||||
* @param fc FontCache to register.
|
||||
*/
|
||||
/* static */ void FontCache::Register(std::unique_ptr<FontCache> &&fc)
|
||||
{
|
||||
if (fc == nullptr) return;
|
||||
|
||||
FontSize fs = fc->fs;
|
||||
|
||||
fc->parent = std::move(FontCache::caches[fs]);
|
||||
FontCache::caches[fs] = std::move(fc);
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)initialize the font cache related things, i.e. load the non-sprite fonts.
|
||||
* @param fontsizes Font sizes to be initialised.
|
||||
*/
|
||||
void InitFontCache(FontSizes fontsizes)
|
||||
/* static */ void FontCache::LoadFontCaches(FontSizes fontsizes)
|
||||
{
|
||||
FontCache::InitializeFontCaches();
|
||||
|
||||
for (FontSize fs : fontsizes) {
|
||||
FontCache *fc = FontCache::Get(fs);
|
||||
if (fc->HasParent()) delete fc;
|
||||
Layouter::ResetFontCache(fs);
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
LoadFreeTypeFont(fs);
|
||||
#elif defined(_WIN32)
|
||||
LoadWin32Font(fs);
|
||||
#elif defined(WITH_COCOA)
|
||||
LoadCoreTextFont(fs);
|
||||
#endif
|
||||
/* Unload everything except the sprite font cache. */
|
||||
while (FontCache::Get(fs)->HasParent()) {
|
||||
FontCache::caches[fs] = std::move(FontCache::caches[fs]->parent);
|
||||
}
|
||||
|
||||
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::TrueType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached information for the specified font caches.
|
||||
* @param fontsizes Font sizes to clear.
|
||||
*/
|
||||
/* static */ void FontCache::ClearFontCaches(FontSizes fontsizes)
|
||||
{
|
||||
for (FontSize fs : fontsizes) {
|
||||
FontCache::Get(fs)->ClearFontCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free everything allocated w.r.t. fonts.
|
||||
*/
|
||||
void UninitFontCache()
|
||||
/* static */ void FontCache::UninitializeFontCaches()
|
||||
{
|
||||
for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) {
|
||||
while (FontCache::Get(fs) != nullptr) delete FontCache::Get(fs);
|
||||
std::ranges::generate(FontCache::caches, []() { return nullptr; });
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
UninitFreeType();
|
||||
#endif /* WITH_FREETYPE */
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA)
|
||||
|
||||
bool SetFallbackFont(FontCacheSettings *, const std::string &, MissingGlyphSearcher *) { return false; }
|
||||
#endif /* !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA) */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef FONTCACHE_H
|
||||
#define FONTCACHE_H
|
||||
|
||||
#include "provider_manager.h"
|
||||
#include "string_type.h"
|
||||
#include "spritecache.h"
|
||||
|
||||
|
@ -20,18 +21,23 @@ static const GlyphID SPRITE_GLYPH = 1U << 30;
|
|||
/** Font cache for basic fonts. */
|
||||
class FontCache {
|
||||
protected:
|
||||
static FontCache *caches[FS_END]; ///< All the font caches.
|
||||
FontCache *parent; ///< The parent of this font cache.
|
||||
static std::array<std::unique_ptr<FontCache>, FS_END> caches; ///< All the font caches.
|
||||
std::unique_ptr<FontCache>parent; ///< The parent of this font cache.
|
||||
const FontSize fs; ///< The size of the font.
|
||||
int height = 0; ///< The height of the font.
|
||||
int ascender = 0; ///< The ascender value of the font.
|
||||
int descender = 0; ///< The descender value of the font.
|
||||
|
||||
FontCache(FontSize fs) : fs(fs) {}
|
||||
static void Register(std::unique_ptr<FontCache> &&fc);
|
||||
|
||||
public:
|
||||
FontCache(FontSize fs);
|
||||
virtual ~FontCache();
|
||||
virtual ~FontCache() {}
|
||||
|
||||
static void InitializeFontCaches();
|
||||
static void UninitializeFontCaches();
|
||||
static void LoadFontCaches(FontSizes fontsizes);
|
||||
static void ClearFontCaches(FontSizes fontsizes);
|
||||
|
||||
/** Default unscaled font heights. */
|
||||
static const int DEFAULT_FONT_HEIGHT[FS_END];
|
||||
|
@ -124,7 +130,7 @@ public:
|
|||
static inline FontCache *Get(FontSize fs)
|
||||
{
|
||||
assert(fs < FS_END);
|
||||
return FontCache::caches[fs];
|
||||
return FontCache::caches[fs].get();
|
||||
}
|
||||
|
||||
static std::string GetName(FontSize fs);
|
||||
|
@ -143,13 +149,6 @@ public:
|
|||
virtual bool IsBuiltInFont() = 0;
|
||||
};
|
||||
|
||||
inline void ClearFontCache(FontSizes fontsizes)
|
||||
{
|
||||
for (FontSize fs : fontsizes) {
|
||||
FontCache::Get(fs)->ClearFontCache();
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the Sprite for a glyph */
|
||||
inline const Sprite *GetGlyph(FontSize size, char32_t key)
|
||||
{
|
||||
|
@ -207,12 +206,39 @@ inline FontCacheSubSetting *GetFontCacheSubSetting(FontSize fs)
|
|||
|
||||
uint GetFontCacheFontSize(FontSize fs);
|
||||
std::string GetFontCacheFontName(FontSize fs);
|
||||
void InitFontCache(FontSizes fontsizes);
|
||||
void UninitFontCache();
|
||||
|
||||
bool GetFontAAState();
|
||||
void SetFont(FontSize fontsize, const std::string &font, uint size);
|
||||
|
||||
/** Different types of font that can be loaded. */
|
||||
enum class FontType : uint8_t {
|
||||
Sprite, ///< Bitmap sprites from GRF files.
|
||||
TrueType, ///< Scalable TrueType fonts.
|
||||
};
|
||||
|
||||
/** Factory for FontCaches. */
|
||||
class FontCacheFactory : public BaseProvider<FontCacheFactory> {
|
||||
public:
|
||||
FontCacheFactory(std::string_view name, std::string_view description) : BaseProvider<FontCacheFactory>(name, description)
|
||||
{
|
||||
ProviderManager<FontCacheFactory>::Register(*this);
|
||||
}
|
||||
|
||||
virtual ~FontCacheFactory()
|
||||
{
|
||||
ProviderManager<FontCacheFactory>::Unregister(*this);
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype) = 0;
|
||||
virtual bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) = 0;
|
||||
};
|
||||
|
||||
class FontProviderManager : ProviderManager<FontCacheFactory> {
|
||||
public:
|
||||
static std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype);
|
||||
static bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback);
|
||||
};
|
||||
|
||||
/* Implemented in spritefontcache.cpp */
|
||||
void InitializeUnicodeGlyphMap();
|
||||
void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite);
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
/** @file freetypefontcache.cpp FreeType font cache implementation. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "../debug.h"
|
||||
#include "../fontcache.h"
|
||||
#include "../fontdetection.h"
|
||||
#include "../blitter/factory.hpp"
|
||||
#include "../core/math_func.hpp"
|
||||
#include "../zoom_func.h"
|
||||
#include "../fileio_func.h"
|
||||
#include "../error_func.h"
|
||||
#include "../../os/unix/font_unix.h"
|
||||
#include "truetypefontcache.h"
|
||||
|
||||
#include "../table/control_codes.h"
|
||||
|
@ -46,9 +46,6 @@ public:
|
|||
const void *GetOSHandle() override { return &face; }
|
||||
};
|
||||
|
||||
FT_Library _ft_library = nullptr;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new FreeTypeFontCache.
|
||||
* @param fs The font size that is going to be cached.
|
||||
|
@ -113,93 +110,6 @@ void FreeTypeFontCache::SetFontSize(int pixels)
|
|||
}
|
||||
}
|
||||
|
||||
static FT_Error LoadFont(FontSize fs, FT_Face face, std::string_view font_name, uint size)
|
||||
{
|
||||
Debug(fontcache, 2, "Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name);
|
||||
|
||||
/* Attempt to select the unicode character map */
|
||||
FT_Error error = FT_Select_Charmap(face, ft_encoding_unicode);
|
||||
if (error == FT_Err_Ok) goto found_face; // Success
|
||||
|
||||
if (error == FT_Err_Invalid_CharMap_Handle) {
|
||||
/* Try to pick a different character map instead. We default to
|
||||
* the first map, but platform_id 0 encoding_id 0 should also
|
||||
* be unicode (strange system...) */
|
||||
FT_CharMap found = face->charmaps[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < face->num_charmaps; i++) {
|
||||
FT_CharMap charmap = face->charmaps[i];
|
||||
if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
|
||||
found = charmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (found != nullptr) {
|
||||
error = FT_Set_Charmap(face, found);
|
||||
if (error == FT_Err_Ok) goto found_face;
|
||||
}
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
return error;
|
||||
|
||||
found_face:
|
||||
new FreeTypeFontCache(fs, face, size);
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the freetype font.
|
||||
* First type to load the fontname as if it were a path. If that fails,
|
||||
* try to resolve the filename of the font using fontconfig, where the
|
||||
* format is 'font family name' or 'font family name, font style'.
|
||||
* @param fs The font size to load.
|
||||
*/
|
||||
void LoadFreeTypeFont(FontSize fs)
|
||||
{
|
||||
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
|
||||
|
||||
std::string font = GetFontCacheFontName(fs);
|
||||
if (font.empty()) return;
|
||||
|
||||
if (_ft_library == nullptr) {
|
||||
if (FT_Init_FreeType(&_ft_library) != FT_Err_Ok) {
|
||||
ShowInfo("Unable to initialize FreeType, using sprite fonts instead");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug(fontcache, 2, "Initialized");
|
||||
}
|
||||
|
||||
FT_Face face = nullptr;
|
||||
|
||||
/* If font is an absolute path to a ttf, try loading that first. */
|
||||
int32_t index = 0;
|
||||
if (settings->os_handle != nullptr) index = *static_cast<const int32_t *>(settings->os_handle);
|
||||
FT_Error error = FT_New_Face(_ft_library, font.c_str(), index, &face);
|
||||
|
||||
if (error != FT_Err_Ok) {
|
||||
/* Check if font is a relative filename in one of our search-paths. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, font);
|
||||
if (!full_font.empty()) {
|
||||
error = FT_New_Face(_ft_library, full_font.c_str(), 0, &face);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try loading based on font face name (OS-wide fonts). */
|
||||
if (error != FT_Err_Ok) error = GetFontByFaceName(font, &face);
|
||||
|
||||
if (error == FT_Err_Ok) {
|
||||
error = LoadFont(fs, face, font, GetFontCacheFontSize(fs));
|
||||
if (error != FT_Err_Ok) {
|
||||
ShowInfo("Unable to use '{}' for {} font, FreeType reported error 0x{:X}, using sprite font instead", font, FontSizeToName(fs), error);
|
||||
}
|
||||
} else {
|
||||
FT_Done_Face(face);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free everything that was allocated for this font cache.
|
||||
*/
|
||||
|
@ -296,19 +206,116 @@ GlyphID FreeTypeFontCache::MapCharToGlyph(char32_t key, bool allow_fallback)
|
|||
return glyph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free everything allocated w.r.t. freetype.
|
||||
*/
|
||||
void UninitFreeType()
|
||||
FT_Library _ft_library = nullptr;
|
||||
|
||||
class FreeTypeFontCacheFactory : public FontCacheFactory {
|
||||
public:
|
||||
FreeTypeFontCacheFactory() : FontCacheFactory("freetype", "FreeType font provider") {}
|
||||
|
||||
virtual ~FreeTypeFontCacheFactory()
|
||||
{
|
||||
FT_Done_FreeType(_ft_library);
|
||||
_ft_library = nullptr;
|
||||
}
|
||||
|
||||
#if !defined(WITH_FONTCONFIG)
|
||||
/**
|
||||
* Loads the freetype font.
|
||||
* First type to load the fontname as if it were a path. If that fails,
|
||||
* try to resolve the filename of the font using fontconfig, where the
|
||||
* format is 'font family name' or 'font family name, font style'.
|
||||
* @param fs The font size to load.
|
||||
*/
|
||||
std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype) override
|
||||
{
|
||||
if (fonttype != FontType::TrueType) return nullptr;
|
||||
|
||||
FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face) { return FT_Err_Cannot_Open_Resource; }
|
||||
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
|
||||
|
||||
#endif /* !defined(WITH_FONTCONFIG) */
|
||||
std::string font = GetFontCacheFontName(fs);
|
||||
if (font.empty()) return nullptr;
|
||||
|
||||
if (_ft_library == nullptr) {
|
||||
if (FT_Init_FreeType(&_ft_library) != FT_Err_Ok) {
|
||||
ShowInfo("Unable to initialize FreeType, using sprite fonts instead");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Debug(fontcache, 2, "Initialized");
|
||||
}
|
||||
|
||||
FT_Face face = nullptr;
|
||||
|
||||
/* If font is an absolute path to a ttf, try loading that first. */
|
||||
int32_t index = 0;
|
||||
if (settings->os_handle != nullptr) index = *static_cast<const int32_t *>(settings->os_handle);
|
||||
FT_Error error = FT_New_Face(_ft_library, font.c_str(), index, &face);
|
||||
|
||||
if (error != FT_Err_Ok) {
|
||||
/* Check if font is a relative filename in one of our search-paths. */
|
||||
std::string full_font = FioFindFullPath(BASE_DIR, font);
|
||||
if (!full_font.empty()) {
|
||||
error = FT_New_Face(_ft_library, full_font.c_str(), 0, &face);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_FONTCONFIG
|
||||
/* Try loading based on font face name (OS-wide fonts). */
|
||||
if (error != FT_Err_Ok) error = GetFontByFaceName(font, &face);
|
||||
#endif /* WITH_FONTCONFIG */
|
||||
|
||||
if (error != FT_Err_Ok) {
|
||||
FT_Done_Face(face);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return LoadFont(fs, face, font, GetFontCacheFontSize(fs));
|
||||
}
|
||||
|
||||
bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) override
|
||||
{
|
||||
#ifdef WITH_FONTCONFIG
|
||||
if (FontConfigFindFallbackFont(settings, language_isocode, callback)) return true;
|
||||
#endif /* WITH_FONTCONFIG */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<FontCache> LoadFont(FontSize fs, FT_Face face, std::string_view font_name, uint size)
|
||||
{
|
||||
Debug(fontcache, 2, "Requested '{}', using '{} {}'", font_name, face->family_name, face->style_name);
|
||||
|
||||
/* Attempt to select the unicode character map */
|
||||
FT_Error error = FT_Select_Charmap(face, ft_encoding_unicode);
|
||||
if (error == FT_Err_Invalid_CharMap_Handle) {
|
||||
/* Try to pick a different character map instead. We default to
|
||||
* the first map, but platform_id 0 encoding_id 0 should also
|
||||
* be unicode (strange system...) */
|
||||
FT_CharMap found = face->charmaps[0];
|
||||
|
||||
for (int i = 0; i < face->num_charmaps; ++i) {
|
||||
FT_CharMap charmap = face->charmaps[i];
|
||||
if (charmap->platform_id == 0 && charmap->encoding_id == 0) {
|
||||
found = charmap;
|
||||
}
|
||||
}
|
||||
|
||||
if (found != nullptr) {
|
||||
error = FT_Set_Charmap(face, found);
|
||||
}
|
||||
}
|
||||
|
||||
if (error != FT_Err_Ok) {
|
||||
FT_Done_Face(face);
|
||||
|
||||
ShowInfo("Unable to use '{}' for {} font, FreeType reported error 0x{:X}, using sprite font instead", font_name, FontSizeToName(fs), error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<FreeTypeFontCache>(fs, face, size);
|
||||
}
|
||||
};
|
||||
|
||||
static FreeTypeFontCacheFactory s_freetype_fontcache_factory;
|
||||
|
||||
#endif /* WITH_FREETYPE */
|
||||
|
|
|
@ -151,3 +151,22 @@ bool SpriteFontCache::GetDrawGlyphShadow()
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
class SpriteFontCacheFactory : public FontCacheFactory {
|
||||
public:
|
||||
SpriteFontCacheFactory() : FontCacheFactory("sprite", "Sprite font provider") {}
|
||||
|
||||
std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype) override
|
||||
{
|
||||
if (fonttype != FontType::Sprite) return nullptr;
|
||||
|
||||
return std::make_unique<SpriteFontCache>(fs);
|
||||
}
|
||||
|
||||
bool FindFallbackFont(struct FontCacheSettings *, const std::string &, class MissingGlyphSearcher *) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static SpriteFontCacheFactory s_sprite_fontcache_factory;
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file fontdetection.h Functions related to detecting/finding the right font. */
|
||||
|
||||
#ifndef FONTDETECTION_H
|
||||
#define FONTDETECTION_H
|
||||
|
||||
#include "fontcache.h"
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
/**
|
||||
* Load a freetype font face with the given font name.
|
||||
* @param font_name The name of the font to load.
|
||||
* @param face The face that has been found.
|
||||
* @return The error we encountered.
|
||||
*/
|
||||
FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face);
|
||||
|
||||
#endif /* WITH_FREETYPE */
|
||||
|
||||
/**
|
||||
* We would like to have a fallback font as the current one
|
||||
* doesn't contain all characters we need.
|
||||
* This function must set all fonts of settings.
|
||||
* @param settings the settings to overwrite the fontname of.
|
||||
* @param language_isocode the language, e.g. en_GB.
|
||||
* @param callback The function to call to check for missing glyphs.
|
||||
* @return true if a font has been set, false otherwise.
|
||||
*/
|
||||
bool SetFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback);
|
||||
|
||||
#endif
|
|
@ -1253,7 +1253,7 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode,
|
|||
*/
|
||||
void LoadStringWidthTable(FontSizes fontsizes)
|
||||
{
|
||||
ClearFontCache(fontsizes);
|
||||
FontCache::ClearFontCaches(fontsizes);
|
||||
|
||||
for (FontSize fs : fontsizes) {
|
||||
for (uint i = 0; i != 224; i++) {
|
||||
|
@ -1820,7 +1820,7 @@ bool AdjustGUIZoom(bool automatic)
|
|||
if (old_font_zoom != _font_zoom) {
|
||||
GfxClearFontSpriteCache();
|
||||
}
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
LoadStringWidthTable();
|
||||
|
||||
SetupWidgetDimensions();
|
||||
|
|
|
@ -245,7 +245,7 @@ static void RealChangeBlitter(std::string_view repl_blitter)
|
|||
|
||||
/* Clear caches that might have sprites for another blitter. */
|
||||
VideoDriver::GetInstance()->ClearSystemSprites();
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
GfxClearSpriteCache();
|
||||
ReInitAllWindows(false);
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ void CheckBlitter()
|
|||
{
|
||||
if (!SwitchNewGRFBlitter()) return;
|
||||
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
GfxClearSpriteCache();
|
||||
ReInitAllWindows(false);
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ void GfxLoadSprites()
|
|||
|
||||
SwitchNewGRFBlitter();
|
||||
VideoDriver::GetInstance()->ClearSystemSprites();
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
GfxInitSpriteMem();
|
||||
LoadSpriteTables();
|
||||
GfxInitPalettes();
|
||||
|
|
|
@ -267,6 +267,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}năm
|
|||
STR_UNITS_PERIODS :{NUM}{NBSP}kỳ
|
||||
|
||||
STR_LIST_SEPARATOR :,{SPACE}
|
||||
STR_TRUNCATION_ELLIPSIS :...
|
||||
|
||||
# Common window strings
|
||||
STR_LIST_FILTER_TITLE :{BLACK}Lọc:
|
||||
|
@ -285,7 +286,7 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Đóng c
|
|||
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Tiêu đề cửa sổ - kéo nó để di chuyển cửa số
|
||||
STR_TOOLTIP_SHADE :{BLACK}Thu gọn cửa sổ - Chỉ hiển thị thanh tiêu đề
|
||||
STR_TOOLTIP_DEBUG :{BLACK}Hiện thông tin debug của NewGRF
|
||||
STR_TOOLTIP_DEFSIZE :{BLACK}Chuyển cửa sổ về kích thước mặc định. Ctrl+Click để lưu kích thước hiện tại làm mặc định
|
||||
STR_TOOLTIP_DEFSIZE :{BLACK}Chuyển cửa sổ về kích thước mặc định. Ctrl+Click để lưu kích thước hiện tại làm mặc định. Ctri+Click kép để thiết lập lại mặc định cũ.
|
||||
STR_TOOLTIP_STICKY :{BLACK}Đánh dấu không-thể-đóng khi bấm nút "Đóng Tất Cả Cửa Sổ". Ctrl+Click để lưu thành trạng thái mặc định
|
||||
STR_TOOLTIP_RESIZE :{BLACK}Click và kéo để thay đổi kích thước cửa sổ
|
||||
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Bật kích cỡ cửa sổ lớn/nhỏ
|
||||
|
@ -451,6 +452,12 @@ STR_SETTINGS_MENU_SANDBOX_OPTIONS :Tuỳ chọn Sa
|
|||
STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Thiết lập hiệu ứng trong suốt
|
||||
STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Hiển thị tên thị trấn
|
||||
STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Hiển thị tên nhà ga
|
||||
STR_SETTINGS_MENU_STATION_NAMES_TRAIN :Ga tàu
|
||||
STR_SETTINGS_MENU_STATION_NAMES_LORRY :Trạm xe tải
|
||||
STR_SETTINGS_MENU_STATION_NAMES_BUS :Trạm xe buýt
|
||||
STR_SETTINGS_MENU_STATION_NAMES_SHIP :Cảng
|
||||
STR_SETTINGS_MENU_STATION_NAMES_PLANE :Sân bay
|
||||
STR_SETTINGS_MENU_STATION_NAMES_GHOST :Trạm ma
|
||||
STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED :Hiển thị tên điểm mốc
|
||||
STR_SETTINGS_MENU_SIGNS_DISPLAYED :Hiển thị ký hiệu
|
||||
STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS :Hiển thị biển hiệu và tên của đối thủ
|
||||
|
@ -627,8 +634,11 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Không h
|
|||
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Bật/tắt đồ thị cho hàng hóa này
|
||||
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
||||
|
||||
STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Lịch sử hàng hóa
|
||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Đã cung cấp
|
||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Đã vận chuyển
|
||||
STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Đã giao
|
||||
STR_GRAPH_INDUSTRY_RANGE_WAITING :Đang chờ...
|
||||
|
||||
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Hiện chi tiết đánh giá chỉ số năng suất
|
||||
|
||||
|
@ -958,11 +968,14 @@ STR_GAME_OPTIONS_TAB_SOUND :Âm thanh
|
|||
STR_GAME_OPTIONS_TAB_SOUND_TOOLTIP :Lựa chọn thiết lập cho âm thanh và nhạc
|
||||
STR_GAME_OPTIONS_TAB_SOCIAL :Xã hội
|
||||
STR_GAME_OPTIONS_TAB_SOCIAL_TOOLTIP :Chọn thiết lập các tích hợp xã hội
|
||||
STR_GAME_OPTIONS_TAB_ADVANCED :Tùy chọn nâng cao
|
||||
STR_GAME_OPTIONS_TAB_ADVANCED_TOOLTIP :Thay đổi tùy chọn nâng cao
|
||||
|
||||
STR_GAME_OPTIONS_VOLUME :Âm lượng
|
||||
STR_GAME_OPTIONS_SFX_VOLUME :Hiệu ứng âm thanh
|
||||
STR_GAME_OPTIONS_MUSIC_VOLUME :Âm nhạc
|
||||
|
||||
STR_GAME_OPTIONS_SETTING :{STRING}: {ORANGE}{STRING}
|
||||
|
||||
STR_GAME_OPTIONS_VOLUME_MARK :{NUM}%
|
||||
|
||||
|
@ -1016,6 +1029,7 @@ STR_GAME_OPTIONS_CURRENCY_IDR :Rupiah Indonesi
|
|||
STR_GAME_OPTIONS_CURRENCY_MYR :Ringgit Malaysia
|
||||
STR_GAME_OPTIONS_CURRENCY_LVL :Lát-vi-a Lats
|
||||
STR_GAME_OPTIONS_CURRENCY_PTE :Escudo Bồ Đào Nha
|
||||
STR_GAME_OPTIONS_CURRENCY_UAH :Hryvnia Ukraina
|
||||
|
||||
STR_GAME_OPTIONS_AUTOSAVE_FRAME :Lưu tự động
|
||||
STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :Lựa chọn khoảng thời gian tự động lưu
|
||||
|
@ -1049,6 +1063,7 @@ STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :Đánh dấu v
|
|||
|
||||
STR_GAME_OPTIONS_VIDEO_DRIVER_INFO :Trình điều khiển hiện tại: {STRING}
|
||||
|
||||
STR_GAME_OPTIONS_INTERFACE :Giao diện
|
||||
|
||||
STR_GAME_OPTIONS_GUI_SCALE_FRAME :Kích thước giao diện
|
||||
STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP :Kéo thanh trượt để điều chỉnh kích thước giao diện. Giữ Ctrl để điều chỉnh liên tục
|
||||
|
@ -1073,6 +1088,7 @@ STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :Sẽ mở trìn
|
|||
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW :Xem trước kết quả khảo sát
|
||||
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP :Hiển thị kết quả khảo sát ở ván chơi hiện tại
|
||||
|
||||
STR_GAME_OPTIONS_DISPLAY :Hiển thị
|
||||
|
||||
STR_GAME_OPTIONS_REFRESH_RATE :Tần số quét màn hình
|
||||
STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :Chọn tần số quét màn hình
|
||||
|
@ -1094,7 +1110,7 @@ STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :Thông tin thê
|
|||
STR_GAME_OPTIONS_ONLINE_CONTENT :Tải Nội Dung
|
||||
STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP :Kiểm tra những nội dung mới & cập nhật để tải về
|
||||
|
||||
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :{LTBLUE}(không có plugins được cài đặt để tích hợp vào nền tảng xã hội)
|
||||
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :(không có plugins được cài đặt để tích hợp vào nền tảng xã hội)
|
||||
|
||||
STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE :{STRING} ({STRING})
|
||||
STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM :Nền tảng:
|
||||
|
@ -1288,6 +1304,9 @@ STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Lãi xuất vay
|
|||
STR_CONFIG_SETTING_RUNNING_COSTS :Chi phí hoạt động: {STRING}
|
||||
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Thiết lập mức độ tính chi phí bảo trì và vận hành đối với phương tiện và hạ tầng giao thông
|
||||
###length 3
|
||||
STR_CONFIG_SETTING_RUNNING_COSTS_LOW :Thấp
|
||||
STR_CONFIG_SETTING_RUNNING_COSTS_MEDIUM :Trung bình
|
||||
STR_CONFIG_SETTING_RUNNING_COSTS_HIGH :Cao
|
||||
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Tốc độ xây dựng: {STRING}
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Giới hạn hành động xây dựng của AI
|
||||
|
@ -1310,6 +1329,9 @@ STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Không có tr
|
|||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Chi phí xây dựng: {STRING}
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Thiết lập mức độ xây dựng và chi phí mua sắm
|
||||
###length 3
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_LOW :Thấp
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_MEDIUM :Trung bình
|
||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HIGH :Cao
|
||||
|
||||
STR_CONFIG_SETTING_RECESSIONS :Suy thoái: {STRING}
|
||||
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Nếu bật, thì các đợt suy thoái sẽ xảy ra vài năm một lần. Trong suy thoái tất cả sản xuất sẽ giảm mạnh (và sẽ trở lại như cũ sau khi suy thoái kết thúc)
|
||||
|
@ -1979,8 +2001,12 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :không cho phé
|
|||
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :cho phép
|
||||
STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :cho phép, tùy chọn bố trí đô thị
|
||||
|
||||
STR_CONFIG_SETTING_HOUSE_PLACER :Đật từng ngôi nhà: {STRING}
|
||||
STR_CONFIG_SETTING_HOUSE_PLACER_HELPTEXT :Bật tùy chọn này cho phép người chơi đặt nhà cửa bằng tay
|
||||
###length 3
|
||||
STR_CONFIG_SETTING_HOUSE_PLACER_FORBIDDEN :Không cho phép
|
||||
STR_CONFIG_SETTING_HOUSE_PLACER_ALLOWED :Cho phép
|
||||
STR_CONFIG_SETTING_HOUSE_PLACER_FULLY_CONSTRUCTED :Cho phép, đã hoàn thành thi công
|
||||
|
||||
STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Nhu cầu vận chuyển hàng đô thị: {STRING}
|
||||
STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Lượng hàng hoá cần vận chuyển ở trong đô thị, tỉ lệ với tổng dân số của độ thị.{}Tăng tỉ lệ bình phương: một đô thị to gấp 2 sẽ tăng 4 lần số hành khách.{}Tăng tỉ lệ thuận: một đô thị tăng gấp 2 sẽ tăng gấp 2 lần số hành khách
|
||||
|
@ -2009,7 +2035,7 @@ STR_CONFIG_SETTING_SOFT_LIMIT :Giới hạn s
|
|||
STR_CONFIG_SETTING_SOFT_LIMIT_HELPTEXT :Số lượng cửa sổ chưa neo (tối đa) trước khi tự động đóng để nhường chỗ khi mở cửa sổ mới
|
||||
STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA}
|
||||
###setting-zero-is-special
|
||||
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :tắt
|
||||
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :Tắt
|
||||
|
||||
STR_CONFIG_SETTING_ZOOM_MIN :Độ phóng to tối đa: {STRING}
|
||||
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Độ phóng to tối đa của cửa sổ. Độ càng cao thì yêu cầu bộ nhớ càng nhiều
|
||||
|
@ -2061,9 +2087,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :Loại hàng h
|
|||
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Chế độ phân phối đối với các loại hàng hóa mặc định: {STRING}
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Không đối xứng" có nghĩa là số lượng hàng hóa tùy ý có thể được gửi theo một trong hai hướng. "Thủ công" có nghĩa là những loại hàng hóa đó sẽ không được phân phối tự động
|
||||
###length 3
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :bằng tay
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :bất đối xứng
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :đối xứng
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :Bằng tay
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :Bất đối xứng
|
||||
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :Đối xứng
|
||||
|
||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Độ chính xác phân phối: {STRING}
|
||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Mức chính xác tính toán đồ thị, nếu giá trị càng cao càng tốn CPU và trò chơi có thể chậm phản ứng, tuy nhiên giá trị thấp sẽ khiến việc phân phối sẽ giảm sự chính xác và bạn sẽ thấy sự khác biệt là hàng hóa không gửi đến chỗ cần đến
|
||||
|
@ -2124,7 +2150,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m)
|
|||
STR_CONFIG_SETTING_LOCALISATION :Tiêu Chuẩn Đo Lường
|
||||
STR_CONFIG_SETTING_GRAPHICS :Đồ họa
|
||||
STR_CONFIG_SETTING_SOUND :Âm thanh
|
||||
STR_CONFIG_SETTING_INTERFACE :Giao Diện
|
||||
STR_CONFIG_SETTING_INTERFACE :Giao diện
|
||||
STR_CONFIG_SETTING_INTERFACE_GENERAL :Tổng quát
|
||||
STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :Vùng nhìn
|
||||
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :Xây Dựng
|
||||
|
@ -2178,6 +2204,8 @@ STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... khô
|
|||
STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH :{WHITE}... trình điều khiển GPU đã làm trò chơi bị lỗi. Tăng tốc phần cứng đã được tắt
|
||||
|
||||
# Intro window
|
||||
STR_INTRO_CAPTION :{WHITE}OpenTTD
|
||||
STR_INTRO_VERSION :OpenTTD {REV}
|
||||
|
||||
STR_INTRO_NEW_GAME :{BLACK}Màn Chơi Mới
|
||||
STR_INTRO_LOAD_GAME :{BLACK}Nạp Ván Chơi
|
||||
|
@ -2311,16 +2339,19 @@ STR_FACE_SIMPLE_TOOLTIP :{BLACK}Trình c
|
|||
STR_FACE_LOAD :{BLACK}Nạp
|
||||
STR_FACE_LOAD_TOOLTIP :{BLACK}Chọn vẻ mặt ưa thích
|
||||
STR_FACE_LOAD_DONE :{WHITE}Vẻ mặt ưa thích đã được nạp từ file thiết lập của OpenTTD.
|
||||
STR_FACE_FACECODE :{BLACK}Khuôn mặt thứ.
|
||||
STR_FACE_FACECODE_TOOLTIP :{BLACK}Xem và/hoặc sửa số vẻ mặt của chủ tịch công ty
|
||||
STR_FACE_FACECODE_CAPTION :{WHITE}Xem và/hoặc chọn số bộ mặt người chơi
|
||||
STR_FACE_FACECODE_SET :{WHITE}Mã số gương mặt mới được thiết lập.
|
||||
STR_FACE_FACECODE_ERR :{WHITE}Không thể thiết lập mã số gương mặt - mã số phải trong khoảng từ 0 đến 4,294,967,295!
|
||||
STR_FACE_FACECODE :{BLACK}Mã số khuôn mặt
|
||||
STR_FACE_FACECODE_TOOLTIP :{BLACK}Xem và/hoặc sửa mã số gương mặt của chủ tịch công ty
|
||||
STR_FACE_FACECODE_CAPTION :{WHITE}Xem và/hoặc chọn mã số gương mặt người chơi
|
||||
STR_FACE_FACECODE_SET :{WHITE}Gương mặt người chơi mới được thiết lập.
|
||||
STR_FACE_FACECODE_ERR :{WHITE}Không thể thiết lập mã số gương mặt - Nhãn và mã số phải hợp lệ
|
||||
STR_FACE_SAVE :{BLACK}Lưu
|
||||
STR_FACE_SAVE_TOOLTIP :{BLACK}Lưu gương mặt yêu thích
|
||||
STR_FACE_SAVE_DONE :{WHITE}Gương mặt yêu thích này sẽ được lưu lại trong tập tin cấu hình OpenTTD .
|
||||
STR_FACE_SETTING_TOGGLE :{STRING} {ORANGE}{STRING}
|
||||
STR_FACE_SETTING_NUMERIC :{STRING} {ORANGE}{NUM} / {NUM}
|
||||
STR_FACE_YES :Đồng ý
|
||||
STR_FACE_NO :Không
|
||||
STR_FACE_STYLE :Kiểu:
|
||||
STR_FACE_HAIR :Tóc:
|
||||
STR_FACE_EYEBROWS :Lông mày:
|
||||
STR_FACE_EYECOLOUR :Màu mắt:
|
||||
|
@ -2607,7 +2638,7 @@ STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} r
|
|||
STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} đã đổi tên thành {STRING}
|
||||
STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} tặng {CURRENCY_LONG} cho {STRING}
|
||||
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Server kết thúc phiên
|
||||
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server khởi động lại...{}Xin chờ...
|
||||
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Server khởi động lại...{}{}Xin chờ...
|
||||
STR_NETWORK_MESSAGE_KICKED :*** {STRING} đã bị đá khỏi ván chơi. Lý do: ({STRING})
|
||||
|
||||
STR_NETWORK_ERROR_COORDINATOR_REGISTRATION_FAILED :{WHITE}Đăng ký server thất bại
|
||||
|
@ -2793,6 +2824,10 @@ STR_PICKER_MODE_USED_TOOLTIP :Bật/tắt hi
|
|||
STR_PICKER_MODE_SAVED :Đã lưu
|
||||
STR_PICKER_MODE_SAVED_TOOLTIP :Bật/tắt hiển thị những hạng mục được lưu
|
||||
|
||||
STR_PICKER_PREVIEW_SHRINK :-
|
||||
STR_PICKER_PREVIEW_SHRINK_TOOLTIP :Giảm chiều cao của ảnh xem trước. Ctrl+Click để giảm đến mức tối thiểu
|
||||
STR_PICKER_PREVIEW_EXPAND :+
|
||||
STR_PICKER_PREVIEW_EXPAND_TOOLTIP :Tăng chiều cao của ảnh xem trước. Ctrl+Click để tăng đến mức tối đa
|
||||
|
||||
STR_PICKER_STATION_CLASS_TOOLTIP :Chọn loại ga bến cần hiển thị
|
||||
STR_PICKER_STATION_TYPE_TOOLTIP :Chọn loại ga bến để xây. Ctrl+Click để thêm hoặc bớt vào danh sách lưu
|
||||
|
@ -2816,6 +2851,7 @@ STR_HOUSE_PICKER_YEARS_FROM :{BLACK}Năm: {O
|
|||
STR_HOUSE_PICKER_YEARS_UNTIL :{BLACK}Năm: {ORANGE}Đến {NUM}
|
||||
STR_HOUSE_PICKER_SIZE :{BLACK}Kích thước: {ORANGE}{NUM}x{NUM} ô
|
||||
STR_HOUSE_PICKER_CARGO_ACCEPTED :{BLACK}Hàng hóa được chấp nhận: {ORANGE}
|
||||
STR_HOUSE_PICKER_CARGO_PRODUCED :{BLACK}Hàng hóa cung cấp: {ORANGE}{CARGO_LIST}
|
||||
|
||||
STR_HOUSE_PICKER_CLASS_ZONE1 :Ngoài rìa
|
||||
STR_HOUSE_PICKER_CLASS_ZONE2 :Ngoại ô
|
||||
|
@ -2824,6 +2860,7 @@ STR_HOUSE_PICKER_CLASS_ZONE4 :Phía trong ngo
|
|||
STR_HOUSE_PICKER_CLASS_ZONE5 :Nội thành
|
||||
|
||||
STR_HOUSE_PICKER_PROTECT_TITLE :Ngăn chặn nâng cấp
|
||||
STR_HOUSE_PICKER_PROTECT_TOOLTIP :Chọn nếu ngôi nhà này có được bảo vệ khỏi việc bị thay thế hay không khi thị trấn phát triển
|
||||
STR_HOUSE_PICKER_PROTECT_OFF :Tắt
|
||||
STR_HOUSE_PICKER_PROTECT_ON :Bật
|
||||
|
||||
|
@ -3031,6 +3068,11 @@ STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Chọn q
|
|||
STR_FOUND_TOWN_CITY :{BLACK}Đô thị
|
||||
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Thành phố phát triển nhanh hơn thị trấn{}Tuỳ thuộc thiết lập, chúng lớn hơn khi khai sinh
|
||||
|
||||
STR_FOUND_TOWN_EXPAND_MODE :{YELLOW}Mở rộng thị trấn:
|
||||
STR_FOUND_TOWN_EXPAND_BUILDINGS :Công trình
|
||||
STR_FOUND_TOWN_EXPAND_BUILDINGS_TOOLTIP :Tăng số công trình của thị trấn
|
||||
STR_FOUND_TOWN_EXPAND_ROADS :Đường sá
|
||||
STR_FOUND_TOWN_EXPAND_ROADS_TOOLTIP :Tăng số đường sá của thị trấn
|
||||
|
||||
STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Quy hoạch đường đô thị:
|
||||
STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP :{BLACK}Chọn để quy hoạch đường bộ trong đô thị
|
||||
|
@ -3103,6 +3145,8 @@ STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}Kiểu x
|
|||
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Giới hạn tốc độ đường ray: {LTBLUE}{VELOCITY}
|
||||
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Hạn chế tốc độ đường bộ: {LTBLUE}{VELOCITY}
|
||||
STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}Tốc độ xe điện giới hạn: {LTBLUE}{VELOCITY}
|
||||
STR_LAND_AREA_INFORMATION_TOWN_CAN_UPGRADE :{BLACK}Nâng cấp thị trấn: {LTBLUE}Có thể
|
||||
STR_LAND_AREA_INFORMATION_TOWN_CANNOT_UPGRADE :{BLACK}Nâng cấp thị trấn: {LTBLUE}Không thể
|
||||
|
||||
# Description of land area of different tiles
|
||||
STR_LAI_CLEAR_DESCRIPTION_ROCKS :Đá
|
||||
|
@ -3111,6 +3155,9 @@ STR_LAI_CLEAR_DESCRIPTION_BARE_LAND :Đất trống
|
|||
STR_LAI_CLEAR_DESCRIPTION_GRASS :Bãi cỏ
|
||||
STR_LAI_CLEAR_DESCRIPTION_FIELDS :Cánh đồng
|
||||
STR_LAI_CLEAR_DESCRIPTION_DESERT :Hoang mạc
|
||||
STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROCKS :Đá có tuyết phủ
|
||||
STR_LAI_CLEAR_DESCRIPTION_SNOWY_ROUGH_LAND :Đất gồ ghề có tuyết phủ
|
||||
STR_LAI_CLEAR_DESCRIPTION_SNOWY_GRASS :Cỏ có tuyết phủ
|
||||
|
||||
STR_LAI_RAIL_DESCRIPTION_TRACK :Đường ray
|
||||
STR_LAI_RAIL_DESCRIPTION_TRACK_WITH_NORMAL_SIGNALS :Đường ray với đèn hiệu khóa
|
||||
|
@ -3579,17 +3626,17 @@ STR_NEWGRF_LIST_COMPATIBLE :{YELLOW}Đã t
|
|||
STR_NEWGRF_LIST_MISSING :{RED}Thiếu files
|
||||
|
||||
# NewGRF 'it's broken' warnings
|
||||
STR_NEWGRF_BROKEN :{WHITE}Hoạt động của NewGRF '{0:STRING}' có thể gây mất đồng bộ hoặc bị treo.
|
||||
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Trạng thái đầu kéo '{1:ENGINE}' được thay đổi khi không ở trong xưởng sửa chữa.
|
||||
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Nó cắt ngắn độ dài của đoàn tàu '{1:ENGINE}' nếu không ở trong xưởng.
|
||||
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Sức chứa của phương tiện bị thay đổi '{1:ENGINE}' khi không ở trong xưởng hoặc vì cải biến
|
||||
STR_NEWGRF_BROKEN :{WHITE}Hoạt động của NewGRF '{PUSH_COLOUR}{0:STRING}{POP_COLOUR}' có thể gây mất đồng bộ hoặc bị treo.
|
||||
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}Trạng thái đầu kéo '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' được thay đổi khi không ở trong xưởng sửa chữa.
|
||||
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}Nó cắt ngắn độ dài của đoàn tàu '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' nếu không ở trong xưởng.
|
||||
STR_NEWGRF_BROKEN_CAPACITY :{WHITE}Sức chứa của phương tiện bị thay đổi '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' khi không ở trong xưởng hoặc vì cải biến
|
||||
STR_BROKEN_VEHICLE_LENGTH :{WHITE}Đoàn tàu '{VEHICLE}' của '{COMPANY}' có độ dài không hợp lệ. Sự cố có thể có căn nguyên từ NewGRFs. Ván chơi có thể mất đồng bộ hoặc bị treo
|
||||
|
||||
STR_NEWGRF_BUGGY :{WHITE}NewGRF '{0:STRING}' không hợp lệ.
|
||||
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Danh mục hàng hoá/cải biến được cho '{1:ENGINE}' khác với danh mục mua được sau khi đã có. Việc này khiến cho việc tự thay thế hay là tự cải biến không chính xác.
|
||||
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' gây ra một vòng lặp vô tận khi gọi hàm callback.
|
||||
STR_NEWGRF_BUGGY :{WHITE}NewGRF '{PUSH_COLOUR}{0:STRING}{POP_COLOUR}' không hợp lệ.
|
||||
STR_NEWGRF_BUGGY_ARTICULATED_CARGO :{WHITE}Danh mục hàng hoá/cải biến được cho '{PUSH_COLOUR}{1:ENGINE}{POP_COLOUR}' khác với danh mục mua được sau khi đã có. Việc này khiến cho việc tự thay thế hay là tự cải biến không chính xác.
|
||||
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK :{WHITE}'{PUSH_COLOUR}{1:STRING}{POP_COLOUR}' gây ra một vòng lặp vô tận khi gọi hàm callback.
|
||||
STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT :{WHITE}Hàm callback {1:HEX} gửi trả kết quả sai/không rõ {2:HEX}
|
||||
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{1:STRING}' trả về loại hàng hoá sản xuất không hợp lệ khi gọi lại tại {2:HEX}
|
||||
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK :{WHITE}'{PUSH_COLOUR}{1:STRING}{POP_COLOUR}' trả về loại hàng hoá sản xuất không hợp lệ khi gọi lại tại {2:HEX}
|
||||
|
||||
# 'User removed essential NewGRFs'-placeholders for stuff without specs
|
||||
STR_NEWGRF_INVALID_CARGO :<sai kiểu hàng>
|
||||
|
@ -3650,6 +3697,10 @@ STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Đổi t
|
|||
|
||||
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Mở rộng
|
||||
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Tăng quy mô đô thị
|
||||
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Mở rộng công trình
|
||||
STR_TOWN_VIEW_EXPAND_BUILDINGS_TOOLTIP :{BLACK}Tăng số công trình của thị trấn
|
||||
STR_TOWN_VIEW_EXPAND_ROADS_BUTTON :{BLACK}Mở rộng đường
|
||||
STR_TOWN_VIEW_EXPAND_ROADS_TOOLTIP :{BLACK}Tăng số đường sá của thị trấn
|
||||
STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Xoá
|
||||
STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Xoá bỏ đô thị này hoàn toàn
|
||||
|
||||
|
@ -3975,6 +4026,8 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Sản l
|
|||
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Sản lượng phút trước:
|
||||
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} ({COMMA}% đã vận chuyển)
|
||||
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Xem vị trí trung tâm của nhà máy. Ctrl+Click mở cửa sổ mới để xem
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Đồ thị hàng hóa
|
||||
STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Xem đồ thị lịch sử kinh doanh hàng hóa
|
||||
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Mức sản lượng: {YELLOW}{COMMA}%
|
||||
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}Nhà máy này đã thông báo sắp đóng cửa!
|
||||
|
||||
|
@ -4386,10 +4439,10 @@ STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Hiện l
|
|||
STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Hiện lộ trình máy bay. Ctrl+Click để hiện lịch trình
|
||||
|
||||
###length VEHICLE_TYPES
|
||||
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu hoả
|
||||
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết xe
|
||||
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu thuỷ
|
||||
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết máy bay
|
||||
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu hoả. Ctrl+Click vào để hiện nhóm của tàu hỏa
|
||||
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết xe. Ctrl+Click để hiện nhóm phương tiện
|
||||
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết tàu thuỷ. Ctrl+Click vào để hiện nhóm của tàu thủy
|
||||
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Hiện chi tiết máy bay. Ctrl+Click để hiện nhóm của máy bay
|
||||
|
||||
###length VEHICLE_TYPES
|
||||
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Tác động đến tàu hỏa hiện tại - bấm để dừng/chạy tàu hỏa
|
||||
|
@ -4644,55 +4697,56 @@ STR_ORDER_ROAD_VEHICLE_DEPOT :Xưởng xe
|
|||
STR_ORDER_SHIP_DEPOT :Xưởng tàu thuỷ
|
||||
###next-name-looks-similar
|
||||
|
||||
STR_ORDER_GO_TO_NEAREST_HANGAR_FORMAT :{STRING} xưởng sân bay gần nhất
|
||||
STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT :{STRING} gần {STRING} nhất
|
||||
STR_ORDER_GO_TO_DEPOT_FORMAT :{STRING} {DEPOT}
|
||||
|
||||
STR_ORDER_REFIT_ORDER :(Cải biến thành {STRING})
|
||||
STR_ORDER_REFIT_STOP_ORDER :(Cải biến thành {STRING} và dừng)
|
||||
STR_ORDER_STOP_ORDER :(Dừng)
|
||||
STR_ORDER_REFIT_ORDER :{SPACE}(Cải biến thành {STRING})
|
||||
STR_ORDER_REFIT_STOP_ORDER :{SPACE}(Cải biến thành {STRING} và dừng)
|
||||
STR_ORDER_STOP_ORDER :{SPACE}(Dừng)
|
||||
|
||||
STR_ORDER_WAIT_TO_UNBUNCH :(Chờ để gỡ gộp)
|
||||
STR_ORDER_WAIT_TO_UNBUNCH :{SPACE}(Chờ để gỡ gộp)
|
||||
|
||||
STR_ORDER_GO_TO_STATION :{STRING} {STATION}
|
||||
STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION :{PUSH_COLOUR}{RED}(Không thể sử dụng trạm){POP_COLOUR} {STRING} {STATION}
|
||||
|
||||
STR_ORDER_IMPLICIT :(Chạy ngầm)
|
||||
STR_ORDER_IMPLICIT :{SPACE}(Chạy ngầm)
|
||||
|
||||
STR_ORDER_FULL_LOAD :(Bốc đầy hàng)
|
||||
STR_ORDER_FULL_LOAD_ANY :(Bốc đủ bất kỳ hàng nào)
|
||||
STR_ORDER_NO_LOAD :(Không bốc xếp)
|
||||
STR_ORDER_UNLOAD :(Dỡ và lấy hàng khác)
|
||||
STR_ORDER_UNLOAD_FULL_LOAD :(Dỡ tất hàng và chờ bốc đầy hàng)
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_ANY :(Dỡ tất hàng và chờ bốc đủ bất kỳ hàng nào)
|
||||
STR_ORDER_UNLOAD_NO_LOAD :(Dỡ tất hàng và để trống)
|
||||
STR_ORDER_TRANSFER :(Trung chuyển hàng và lấy hàng khác)
|
||||
STR_ORDER_TRANSFER_FULL_LOAD :(Trung chuyển và chờ bốc đầy hàng)
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_ANY :(Trung chuyển và chờ bốc đủ hàng bất kỳ)
|
||||
STR_ORDER_TRANSFER_NO_LOAD :(Trung chuyển và để trống)
|
||||
STR_ORDER_NO_UNLOAD :(Không dỡ và lấy hàng)
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD :(Không dỡ và chờ lấy thêm đầy hàng)
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :(Không dỡ và chờ lấy đủ hàng bất kỳ)
|
||||
STR_ORDER_NO_UNLOAD_NO_LOAD :(Không bốc hàng và không dỡ hàng)
|
||||
STR_ORDER_FULL_LOAD :{SPACE}(Bốc đầy hàng)
|
||||
STR_ORDER_FULL_LOAD_ANY :{SPACE}(Bốc đủ bất kỳ hàng nào)
|
||||
STR_ORDER_NO_LOAD :{SPACE}(Không bốc xếp)
|
||||
STR_ORDER_UNLOAD :{SPACE}(Dỡ và lấy hàng khác)
|
||||
STR_ORDER_UNLOAD_FULL_LOAD :{SPACE}(Dỡ tất hàng và chờ bốc đầy hàng)
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_ANY :{SPACE}(Dỡ tất hàng và chờ bốc đủ bất kỳ hàng nào)
|
||||
STR_ORDER_UNLOAD_NO_LOAD :{SPACE}(Dỡ tất hàng và để trống)
|
||||
STR_ORDER_TRANSFER :{SPACE}(Trung chuyển hàng và lấy hàng khác)
|
||||
STR_ORDER_TRANSFER_FULL_LOAD :{SPACE}(Trung chuyển và chờ bốc đầy hàng)
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_ANY :{SPACE}(Trung chuyển và chờ bốc đủ hàng bất kỳ)
|
||||
STR_ORDER_TRANSFER_NO_LOAD :{SPACE}(Trung chuyển và để trống)
|
||||
STR_ORDER_NO_UNLOAD :{SPACE}(Không dỡ và lấy hàng)
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD :{SPACE}(Không dỡ và chờ lấy thêm đầy hàng)
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY :{SPACE}(Không dỡ và chờ lấy đủ hàng bất kỳ)
|
||||
STR_ORDER_NO_UNLOAD_NO_LOAD :{SPACE}(Không bốc hàng và không dỡ hàng)
|
||||
|
||||
STR_ORDER_AUTO_REFIT :(Tự cải biến thành {STRING})
|
||||
STR_ORDER_FULL_LOAD_REFIT :(Tự cải biến và chất đầy {STRING})
|
||||
STR_ORDER_FULL_LOAD_ANY_REFIT :(Tự cải biến và chất đầy bất kỳ {STRING})
|
||||
STR_ORDER_UNLOAD_REFIT :(Dỡ hàng và tự cải biến để lấy {STRING})
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_REFIT :(Dỡ hàng và tự cải biến đề bốc đầy {STRING})
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :(Dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
STR_ORDER_TRANSFER_REFIT :(Trung chuyển và tự cải biến để lấy {STRING})
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_REFIT :(Trung chuyển và tự cải biến đề bốc đầy {STRING})
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :(Trung chuyển và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
STR_ORDER_NO_UNLOAD_REFIT :(Không dỡ hàng và tự cái biến để lấy {STRING})
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :(Không dỡ hàng và tự cải biến để bốc đầy {STRING})
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :(Không dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
STR_ORDER_AUTO_REFIT :{SPACE}(Tự cải biến thành {STRING})
|
||||
STR_ORDER_FULL_LOAD_REFIT :{SPACE}(Tự cải biến và chất đầy {STRING})
|
||||
STR_ORDER_FULL_LOAD_ANY_REFIT :{SPACE}(Tự cải biến và chất đầy bất kỳ {STRING})
|
||||
STR_ORDER_UNLOAD_REFIT :{SPACE}(Dỡ hàng và tự cải biến để lấy {STRING})
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_REFIT :{SPACE}(Dỡ hàng và tự cải biến đề bốc đầy {STRING})
|
||||
STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT :{SPACE}(Dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
STR_ORDER_TRANSFER_REFIT :{SPACE}(Trung chuyển và tự cải biến để lấy {STRING})
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_REFIT :{SPACE}(Trung chuyển và tự cải biến đề bốc đầy {STRING})
|
||||
STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT :{SPACE}(Trung chuyển và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
STR_ORDER_NO_UNLOAD_REFIT :{SPACE}(Không dỡ hàng và tự cái biến để lấy {STRING})
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT :{SPACE}(Không dỡ hàng và tự cải biến để bốc đầy {STRING})
|
||||
STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT :{SPACE}(Không dỡ hàng và tự cải biến để bốc đầy bất kỳ {STRING})
|
||||
|
||||
STR_ORDER_AUTO_REFIT_ANY :hàng hóa sẵn có
|
||||
|
||||
###length 3
|
||||
STR_ORDER_STOP_LOCATION_NEAR_END :[đỗ ở đầu gần]
|
||||
STR_ORDER_STOP_LOCATION_MIDDLE :[đỗ ở giữa]
|
||||
STR_ORDER_STOP_LOCATION_FAR_END :[đỗ ở đầu xa]
|
||||
STR_ORDER_STOP_LOCATION_NEAR_END :{SPACE}[đỗ ở đầu gần]
|
||||
STR_ORDER_STOP_LOCATION_MIDDLE :{SPACE}[đỗ ở giữa]
|
||||
STR_ORDER_STOP_LOCATION_FAR_END :{SPACE}[đỗ ở đầu xa]
|
||||
|
||||
STR_ORDER_OUT_OF_RANGE :{RED} (Điểm đến kế tiếp ngoài tầm xa)
|
||||
|
||||
|
@ -4712,14 +4766,15 @@ STR_TIMETABLE_TOOLTIP :{BLACK}Lịch t
|
|||
STR_TIMETABLE_NO_TRAVEL :Không di chuyển
|
||||
STR_TIMETABLE_NOT_TIMETABLEABLE :Hành trình (tự động; tính thời gian theo lịch trình thủ công kế tiếp)
|
||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Di chuyển (không bó buộc theo lịch trình)
|
||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Hành trình với tốc độ tối đa là {VELOCITY} (chưa dựng lịch trình)
|
||||
STR_TIMETABLE_TRAVEL_FOR :Di chuyển trong {STRING}
|
||||
STR_TIMETABLE_TRAVEL_FOR_SPEED :Lộ trình {STRING} với tốc độ tối đa {VELOCITY}
|
||||
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Lộ trình (cho {STRING}, chưa có lịch trình)
|
||||
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Lộ trình (cho {STRING}, chưa có lịch trình) với tốc độ đối đa {VELOCITY}
|
||||
STR_TIMETABLE_STAY_FOR_ESTIMATED :(ở lại {STRING}, chưa có lịch trình)
|
||||
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :(di chuyển đến {STRING}, chưa có lịch trình)
|
||||
STR_TIMETABLE_STAY_FOR :và ở lại trong {STRING}
|
||||
STR_TIMETABLE_AND_TRAVEL_FOR :và di chuyển trong {STRING}
|
||||
STR_TIMETABLE_STAY_FOR_ESTIMATED :{SPACE}(ở lại {STRING}, chưa có lịch trình)
|
||||
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :{SPACE}(di chuyển đến {STRING}, chưa có lịch trình)
|
||||
STR_TIMETABLE_STAY_FOR :{SPACE}và ở lại trong {STRING}
|
||||
STR_TIMETABLE_AND_TRAVEL_FOR :{SPACE}và di chuyển trong {STRING}
|
||||
|
||||
STR_TIMETABLE_APPROX_TIME :{BLACK}Lịch trình này sẽ mất khoảng {STRING} để hoàn thành
|
||||
STR_TIMETABLE_TOTAL_TIME :{BLACK}Lịch trình này sẽ mất {STRING} để hoàn thành
|
||||
|
@ -4738,12 +4793,14 @@ STR_TIMETABLE_START_SECONDS_QUERY :Số giây cho
|
|||
|
||||
STR_TIMETABLE_CHANGE_TIME :{BLACK}Đổi thời gian
|
||||
STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Thay đổi thời lượng của điểm lộ trình được phép sử dụng. Ctrl+Click đặt thời gian cho mọi lộ trình
|
||||
STR_TIMETABLE_CHANGE_TIME_QUERY :Thay đổi thời gian
|
||||
|
||||
STR_TIMETABLE_CLEAR_TIME :{BLACK}Xoá thời gian
|
||||
STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Xóa thời lượng áp dụng cho điểm lộ trình. Ctrl+Click xoá tất cả thời gian cho mọi lộ trình
|
||||
|
||||
STR_TIMETABLE_CHANGE_SPEED :{BLACK}Thay Đổi Giới Hạn Tốc Độ
|
||||
STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Thay đổi tốc độ tối đa của lộ trình được chọn. Ctrl+Click đặt tốc độ cho mọi lộ trình
|
||||
STR_TIMETABLE_CHANGE_SPEED_QUERY :Thay đổi giới hạn tốc độ
|
||||
|
||||
STR_TIMETABLE_CLEAR_SPEED :{BLACK}Xóa Giới Hạn Tốc Độ
|
||||
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Xóa tốc độ đối đa đối với lộ trình được chọn. Ctrl+Click xoá tốc độ cho mọi lộ trình
|
||||
|
@ -4907,7 +4964,7 @@ STR_GAME_SAVELOAD_NOT_AVAILABLE :<không có s
|
|||
STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}Lưu ván chơi sẽ không có xe điện. Những công trình cho xe điện sẽ bị xoá bỏ
|
||||
|
||||
# Map generation messages
|
||||
STR_ERROR_COULD_NOT_CREATE_TOWN :{WHITE}Sinh bản đồ bị ngưng...{}... không có nơi đặt đô thị
|
||||
STR_ERROR_COULD_NOT_CREATE_TOWN :{WHITE}Sinh bản đồ bị ngưng...{}{}... không có nơi đặt đô thị
|
||||
STR_ERROR_NO_TOWN_IN_SCENARIO :{WHITE}... không có đô thị nào ở màn chơi kịch bản này
|
||||
|
||||
STR_ERROR_PNGMAP :{WHITE}Không thể nạp nền từ file PNG...
|
||||
|
@ -4946,6 +5003,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Yêu c
|
|||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Tạo dốc bị sai hướng
|
||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Không làm thế này được...
|
||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Cần giải toả nhà cửa trước
|
||||
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... công trình được bảo vệ
|
||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Không thể dọn dẹp khu vực này...
|
||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... điểm không phù hợp
|
||||
STR_ERROR_ALREADY_BUILT :{WHITE}... đã xây rồi
|
||||
|
@ -4998,7 +5056,7 @@ STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... quá
|
|||
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... quá nhiều đô thị
|
||||
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... không còn khoảng trống nào trên bản đồ
|
||||
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Xây dựng cầu đường đang tiến hành
|
||||
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Không thể xoá đo thị này...{}Có một ga, bến hoặc xưởng thuộc đô thị hoặc là 1 ô đất của đô thị không thể xoá được.
|
||||
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Không thể xoá đo thị này...{}{}Có một ga, bến hoặc xưởng thuộc đô thị hoặc là 1 ô đất của đô thị không thể xoá được.
|
||||
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... không có nơi nào hợp lý để dựng tượng đài ở trung tâm đô thị này
|
||||
STR_ERROR_CAN_T_BUILD_HOUSE :{WHITE}Không thể xây dựng nhà...
|
||||
|
||||
|
@ -5825,6 +5883,7 @@ STR_CURRENCY_SHORT_GIGA :{NBSP}tỷ
|
|||
STR_CURRENCY_SHORT_TERA :{NBSP}ktỷ
|
||||
|
||||
STR_JUST_CARGO :{CARGO_LONG}
|
||||
STR_JUST_LEFT_ARROW :{LEFT_ARROW}
|
||||
STR_JUST_RIGHT_ARROW :{RIGHT_ARROW}
|
||||
STR_JUST_CHECKMARK :{CHECKMARK}
|
||||
STR_JUST_COMMA :{COMMA}
|
||||
|
@ -5864,3 +5923,11 @@ STR_SHIP :{BLACK}{SHIP}
|
|||
STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY})
|
||||
|
||||
STR_BADGE_NAME_LIST :{STRING}: {GOLD}{STRING}
|
||||
STR_BADGE_CONFIG_MENU_TOOLTIP :Mở thiết lập phù hiệu
|
||||
STR_BADGE_CONFIG_RESET :Thiêt lập lại
|
||||
STR_BADGE_CONFIG_ICONS :{WHITE}Ảnh phù hiệu
|
||||
STR_BADGE_CONFIG_FILTERS :{WHITE}Bộ lọc phù hiệu
|
||||
STR_BADGE_CONFIG_PREVIEW :Ảnh xem trước
|
||||
STR_BADGE_CONFIG_NAME :Tên
|
||||
STR_BADGE_FILTER_ANY_LABEL :Bất cứ {STRING} nào
|
||||
STR_BADGE_FILTER_IS_LABEL :{STRING} là {STRING}
|
||||
|
|
|
@ -315,7 +315,7 @@ static void ShutdownGame()
|
|||
/* No NewGRFs were loaded when it was still bootstrapping. */
|
||||
if (_game_mode != GM_BOOTSTRAP) ResetNewGRFData();
|
||||
|
||||
UninitFontCache();
|
||||
FontCache::UninitializeFontCaches();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -700,7 +700,7 @@ int openttd_main(std::span<std::string_view> arguments)
|
|||
InitializeLanguagePacks();
|
||||
|
||||
/* Initialize the font cache */
|
||||
InitFontCache(FONTSIZES_REQUIRED);
|
||||
FontCache::LoadFontCaches(FONTSIZES_REQUIRED);
|
||||
|
||||
/* This must be done early, since functions use the SetWindowDirty* calls */
|
||||
InitWindowSystem();
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "../../blitter/factory.hpp"
|
||||
#include "../../error_func.h"
|
||||
#include "../../fileio_func.h"
|
||||
#include "../../fontdetection.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../strings_func.h"
|
||||
#include "../../zoom_func.h"
|
||||
|
@ -24,91 +23,6 @@
|
|||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback)
|
||||
{
|
||||
/* Determine fallback font using CoreText. This uses the language isocode
|
||||
* to find a suitable font. CoreText is available from 10.5 onwards. */
|
||||
std::string lang;
|
||||
if (language_isocode == "zh_TW") {
|
||||
/* Traditional Chinese */
|
||||
lang = "zh-Hant";
|
||||
} else if (language_isocode == "zh_CN") {
|
||||
/* Simplified Chinese */
|
||||
lang = "zh-Hans";
|
||||
} else {
|
||||
/* Just copy the first part of the isocode. */
|
||||
lang = language_isocode.substr(0, language_isocode.find('_'));
|
||||
}
|
||||
|
||||
/* Create a font descriptor matching the wanted language and latin (english) glyphs.
|
||||
* Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */
|
||||
CFStringRef lang_codes[2];
|
||||
lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang.c_str(), kCFStringEncodingUTF8);
|
||||
lang_codes[1] = CFSTR("en");
|
||||
CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks);
|
||||
CFAutoRelease<CFDictionaryRef> lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void *const *>(&kCTFontLanguagesAttribute)), (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
|
||||
CFAutoRelease<CTFontDescriptorRef> lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get()));
|
||||
CFRelease(lang_arr);
|
||||
CFRelease(lang_codes[0]);
|
||||
|
||||
/* Get array of all font descriptors for the wanted language. */
|
||||
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void *const *>(&kCTFontLanguagesAttribute)), 1, &kCFTypeSetCallBacks));
|
||||
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get()));
|
||||
|
||||
bool result = false;
|
||||
for (int tries = 0; tries < 2; tries++) {
|
||||
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) {
|
||||
CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i);
|
||||
|
||||
/* Get font traits. */
|
||||
CFAutoRelease<CFDictionaryRef> traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute));
|
||||
CTFontSymbolicTraits symbolic_traits;
|
||||
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
|
||||
|
||||
/* Skip symbol fonts and vertical fonts. */
|
||||
if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue;
|
||||
/* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */
|
||||
if (symbolic_traits & kCTFontBoldTrait) continue;
|
||||
/* Select monospaced fonts if asked for. */
|
||||
if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue;
|
||||
|
||||
/* Get font name. */
|
||||
char buffer[128];
|
||||
CFAutoRelease<CFStringRef> font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute));
|
||||
CFStringGetCString(font_name.get(), buffer, std::size(buffer), kCFStringEncodingUTF8);
|
||||
|
||||
/* Serif fonts usually look worse on-screen with only small
|
||||
* font sizes. As such, we try for a sans-serif font first.
|
||||
* If we can't find one in the first try, try all fonts. */
|
||||
if (tries == 0 && (symbolic_traits & kCTFontClassMaskTrait) != (CTFontStylisticClass)kCTFontSansSerifClass) continue;
|
||||
|
||||
/* There are some special fonts starting with an '.' and the last
|
||||
* resort font that aren't usable. Skip them. */
|
||||
std::string_view name{buffer};
|
||||
if (name.starts_with(".") || name.starts_with("LastResort")) continue;
|
||||
|
||||
/* Save result. */
|
||||
callback->SetFontNames(settings, name);
|
||||
if (!callback->FindMissingGlyphs()) {
|
||||
Debug(fontcache, 2, "CT-Font for {}: {}", language_isocode, name);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
/* For some OS versions, the font 'Arial Unicode MS' does not report all languages it
|
||||
* supports. If we didn't find any other font, just try it, maybe we get lucky. */
|
||||
callback->SetFontNames(settings, "Arial Unicode MS");
|
||||
result = !callback->FindMissingGlyphs();
|
||||
}
|
||||
|
||||
callback->FindMissingGlyphs();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
CoreTextFontCache::CoreTextFontCache(FontSize fs, CFAutoRelease<CTFontDescriptorRef> &&font, int pixels) : TrueTypeFontCache(fs, pixels), font_desc(std::move(font))
|
||||
{
|
||||
this->SetFontSize(pixels);
|
||||
|
@ -287,39 +201,9 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
|
|||
return this->SetGlyphPtr(key, std::move(new_glyph)).GetSprite();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
class CoreTextFontCacheFactory : public FontCacheFactory {
|
||||
public:
|
||||
CoreTextFontCacheFactory() : FontCacheFactory("coretext", "CoreText font loader") {}
|
||||
|
||||
/**
|
||||
* Loads the TrueType font.
|
||||
|
@ -327,12 +211,14 @@ static CTFontDescriptorRef LoadFontFromFile(const std::string &font_name)
|
|||
* fallback search, use it. Otherwise, try to resolve it by font name.
|
||||
* @param fs The font size to load.
|
||||
*/
|
||||
void LoadCoreTextFont(FontSize fs)
|
||||
std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype) override
|
||||
{
|
||||
if (fonttype != FontType::TrueType) return nullptr;
|
||||
|
||||
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
|
||||
|
||||
std::string font = GetFontCacheFontName(fs);
|
||||
if (font.empty()) return;
|
||||
if (font.empty()) return nullptr;
|
||||
|
||||
CFAutoRelease<CTFontDescriptorRef> font_ref;
|
||||
|
||||
|
@ -367,8 +253,130 @@ void LoadCoreTextFont(FontSize fs)
|
|||
|
||||
if (!font_ref) {
|
||||
ShowInfo("Unable to use '{}' for {} font, using sprite font instead", font, FontSizeToName(fs));
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
new CoreTextFontCache(fs, std::move(font_ref), GetFontCacheFontSize(fs));
|
||||
return std::make_unique<CoreTextFontCache>(fs, std::move(font_ref), GetFontCacheFontSize(fs));
|
||||
}
|
||||
|
||||
bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) override
|
||||
{
|
||||
/* Determine fallback font using CoreText. This uses the language isocode
|
||||
* to find a suitable font. CoreText is available from 10.5 onwards. */
|
||||
std::string lang;
|
||||
if (language_isocode == "zh_TW") {
|
||||
/* Traditional Chinese */
|
||||
lang = "zh-Hant";
|
||||
} else if (language_isocode == "zh_CN") {
|
||||
/* Simplified Chinese */
|
||||
lang = "zh-Hans";
|
||||
} else {
|
||||
/* Just copy the first part of the isocode. */
|
||||
lang = language_isocode.substr(0, language_isocode.find('_'));
|
||||
}
|
||||
|
||||
/* Create a font descriptor matching the wanted language and latin (english) glyphs.
|
||||
* Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */
|
||||
CFStringRef lang_codes[2];
|
||||
lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang.c_str(), kCFStringEncodingUTF8);
|
||||
lang_codes[1] = CFSTR("en");
|
||||
CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks);
|
||||
CFAutoRelease<CFDictionaryRef> lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void *const *>(&kCTFontLanguagesAttribute)), (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
|
||||
CFAutoRelease<CTFontDescriptorRef> lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get()));
|
||||
CFRelease(lang_arr);
|
||||
CFRelease(lang_codes[0]);
|
||||
|
||||
/* Get array of all font descriptors for the wanted language. */
|
||||
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void *const *>(&kCTFontLanguagesAttribute)), 1, &kCFTypeSetCallBacks));
|
||||
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get()));
|
||||
|
||||
bool result = false;
|
||||
for (int tries = 0; tries < 2; tries++) {
|
||||
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) {
|
||||
CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i);
|
||||
|
||||
/* Get font traits. */
|
||||
CFAutoRelease<CFDictionaryRef> traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute));
|
||||
CTFontSymbolicTraits symbolic_traits;
|
||||
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
|
||||
|
||||
/* Skip symbol fonts and vertical fonts. */
|
||||
if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue;
|
||||
/* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */
|
||||
if (symbolic_traits & kCTFontBoldTrait) continue;
|
||||
/* Select monospaced fonts if asked for. */
|
||||
if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue;
|
||||
|
||||
/* Get font name. */
|
||||
char buffer[128];
|
||||
CFAutoRelease<CFStringRef> font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute));
|
||||
CFStringGetCString(font_name.get(), buffer, std::size(buffer), kCFStringEncodingUTF8);
|
||||
|
||||
/* Serif fonts usually look worse on-screen with only small
|
||||
* font sizes. As such, we try for a sans-serif font first.
|
||||
* If we can't find one in the first try, try all fonts. */
|
||||
if (tries == 0 && (symbolic_traits & kCTFontClassMaskTrait) != (CTFontStylisticClass)kCTFontSansSerifClass) continue;
|
||||
|
||||
/* There are some special fonts starting with an '.' and the last
|
||||
* resort font that aren't usable. Skip them. */
|
||||
std::string_view name{buffer};
|
||||
if (name.starts_with(".") || name.starts_with("LastResort")) continue;
|
||||
|
||||
/* Save result. */
|
||||
callback->SetFontNames(settings, name);
|
||||
if (!callback->FindMissingGlyphs()) {
|
||||
Debug(fontcache, 2, "CT-Font for {}: {}", language_isocode, name);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
/* For some OS versions, the font 'Arial Unicode MS' does not report all languages it
|
||||
* supports. If we didn't find any other font, just try it, maybe we get lucky. */
|
||||
callback->SetFontNames(settings, "Arial Unicode MS");
|
||||
result = !callback->FindMissingGlyphs();
|
||||
}
|
||||
|
||||
callback->FindMissingGlyphs();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
static CoreTextFontCacheFactory s_coretext_fontcache_Factory;
|
||||
|
|
|
@ -12,6 +12,7 @@ add_files(
|
|||
|
||||
add_files(
|
||||
font_unix.cpp
|
||||
font_unix.h
|
||||
CONDITION Fontconfig_FOUND
|
||||
)
|
||||
|
||||
|
|
|
@ -11,17 +11,17 @@
|
|||
|
||||
#include "../../misc/autorelease.hpp"
|
||||
#include "../../debug.h"
|
||||
#include "../../fontdetection.h"
|
||||
#include "../../fontcache.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../strings_func.h"
|
||||
#include "font_unix.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
extern FT_Library _ft_library;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +61,12 @@ static std::tuple<std::string, std::string> SplitFontFamilyAndStyle(std::string_
|
|||
return { std::string(font_name.substr(0, separator)), std::string(font_name.substr(begin)) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a freetype font face with the given font name.
|
||||
* @param font_name The name of the font to load.
|
||||
* @param face The face that has been found.
|
||||
* @return The error we encountered.
|
||||
*/
|
||||
FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face)
|
||||
{
|
||||
FT_Error err = FT_Err_Cannot_Open_Resource;
|
||||
|
@ -117,7 +123,7 @@ FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face)
|
|||
return err;
|
||||
}
|
||||
|
||||
bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback)
|
||||
bool FontConfigFindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
|
@ -182,6 +188,6 @@ bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_is
|
|||
if (best_font == nullptr) return false;
|
||||
|
||||
callback->SetFontNames(settings, best_font, &best_index);
|
||||
InitFontCache(callback->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
FontCache::LoadFontCaches(callback->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file font_unix.h Functions related to detecting/finding the right font. */
|
||||
|
||||
#ifndef FONT_UNIX_H
|
||||
#define FONT_UNIX_H
|
||||
|
||||
#ifdef WITH_FONTCONFIG
|
||||
|
||||
#include "../../fontcache.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face);
|
||||
|
||||
bool FontConfigFindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback);
|
||||
|
||||
#endif /* WITH_FONTCONFIG */
|
||||
|
||||
#endif /* FONT_UNIX_H */
|
|
@ -15,7 +15,6 @@
|
|||
#include "../../fileio_func.h"
|
||||
#include "../../fontcache.h"
|
||||
#include "../../fontcache/truetypefontcache.h"
|
||||
#include "../../fontdetection.h"
|
||||
#include "../../library_loader.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../strings_func.h"
|
||||
|
@ -85,32 +84,6 @@ static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXT
|
|||
return 0; // stop enumerating
|
||||
}
|
||||
|
||||
bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback)
|
||||
{
|
||||
Debug(fontcache, 1, "Trying fallback fonts");
|
||||
EFCParam langInfo;
|
||||
std::wstring lang = OTTD2FS(language_isocode.substr(0, language_isocode.find('_')));
|
||||
if (GetLocaleInfoEx(lang.c_str(), LOCALE_FONTSIGNATURE, reinterpret_cast<LPWSTR>(&langInfo.locale), sizeof(langInfo.locale) / sizeof(wchar_t)) == 0) {
|
||||
/* Invalid isocode or some other mysterious error, can't determine fallback font. */
|
||||
Debug(fontcache, 1, "Can't get locale info for fallback font (isocode={})", language_isocode);
|
||||
return false;
|
||||
}
|
||||
langInfo.settings = settings;
|
||||
langInfo.callback = callback;
|
||||
|
||||
LOGFONT font;
|
||||
/* Enumerate all fonts. */
|
||||
font.lfCharSet = DEFAULT_CHARSET;
|
||||
font.lfFaceName[0] = '\0';
|
||||
font.lfPitchAndFamily = 0;
|
||||
|
||||
HDC dc = GetDC(nullptr);
|
||||
int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0);
|
||||
ReleaseDC(nullptr, dc);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Win32FontCache.
|
||||
* @param fs The font size that is going to be cached.
|
||||
|
@ -293,6 +266,85 @@ void Win32FontCache::ClearFontCache()
|
|||
return allow_fallback && key >= SCC_SPRITE_START && key <= SCC_SPRITE_END ? this->parent->MapCharToGlyph(key) : 0;
|
||||
}
|
||||
|
||||
class Win32FontCacheFactory : FontCacheFactory {
|
||||
public:
|
||||
Win32FontCacheFactory() : FontCacheFactory("win32", "Win32 font loader") {}
|
||||
|
||||
/**
|
||||
* Loads the GDI font.
|
||||
* If a GDI font description is present, e.g. from the automatic font
|
||||
* fallback search, use it. Otherwise, try to resolve it by font name.
|
||||
* @param fs The font size to load.
|
||||
*/
|
||||
std::unique_ptr<FontCache> LoadFont(FontSize fs, FontType fonttype) override
|
||||
{
|
||||
if (fonttype != FontType::TrueType) return nullptr;
|
||||
|
||||
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
|
||||
|
||||
std::string font = GetFontCacheFontName(fs);
|
||||
if (font.empty()) return nullptr;
|
||||
|
||||
LOGFONT logfont{};
|
||||
logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH;
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
|
||||
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
|
||||
if (settings->os_handle != nullptr) {
|
||||
logfont = *(const LOGFONT *)settings->os_handle;
|
||||
} else if (font.find('.') != std::string::npos) {
|
||||
/* Might be a font file name, try load it. */
|
||||
if (!TryLoadFontFromFile(font, logfont)) {
|
||||
ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font, FontSizeToName(fs));
|
||||
}
|
||||
}
|
||||
|
||||
if (logfont.lfFaceName[0] == 0) {
|
||||
logfont.lfWeight = StrContainsIgnoreCase(font, " bold") ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts.
|
||||
convert_to_fs(font, logfont.lfFaceName);
|
||||
}
|
||||
|
||||
return LoadWin32Font(fs, logfont, GetFontCacheFontSize(fs), font);
|
||||
}
|
||||
|
||||
bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) override
|
||||
{
|
||||
Debug(fontcache, 1, "Trying fallback fonts");
|
||||
EFCParam langInfo;
|
||||
std::wstring lang = OTTD2FS(language_isocode.substr(0, language_isocode.find('_')));
|
||||
if (GetLocaleInfoEx(lang.c_str(), LOCALE_FONTSIGNATURE, reinterpret_cast<LPWSTR>(&langInfo.locale), sizeof(langInfo.locale) / sizeof(wchar_t)) == 0) {
|
||||
/* Invalid isocode or some other mysterious error, can't determine fallback font. */
|
||||
Debug(fontcache, 1, "Can't get locale info for fallback font (isocode={})", language_isocode);
|
||||
return false;
|
||||
}
|
||||
langInfo.settings = settings;
|
||||
langInfo.callback = callback;
|
||||
|
||||
LOGFONT font;
|
||||
/* Enumerate all fonts. */
|
||||
font.lfCharSet = DEFAULT_CHARSET;
|
||||
font.lfFaceName[0] = '\0';
|
||||
font.lfPitchAndFamily = 0;
|
||||
|
||||
HDC dc = GetDC(nullptr);
|
||||
int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0);
|
||||
ReleaseDC(nullptr, dc);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<FontCache> LoadWin32Font(FontSize fs, const LOGFONT &logfont, uint size, std::string_view 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 nullptr;
|
||||
}
|
||||
DeleteObject(font);
|
||||
|
||||
return std::make_unique<Win32FontCache>(fs, logfont, size);
|
||||
}
|
||||
|
||||
static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont)
|
||||
{
|
||||
|
@ -342,50 +394,6 @@ static bool TryLoadFontFromFile(const std::string &font_name, LOGFONT &logfont)
|
|||
|
||||
return logfont.lfFaceName[0] != 0;
|
||||
}
|
||||
};
|
||||
|
||||
static void LoadWin32Font(FontSize fs, const LOGFONT &logfont, uint size, std::string_view 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
|
||||
* fallback search, use it. Otherwise, try to resolve it by font name.
|
||||
* @param fs The font size to load.
|
||||
*/
|
||||
void LoadWin32Font(FontSize fs)
|
||||
{
|
||||
FontCacheSubSetting *settings = GetFontCacheSubSetting(fs);
|
||||
|
||||
std::string font = GetFontCacheFontName(fs);
|
||||
if (font.empty()) return;
|
||||
|
||||
LOGFONT logfont{};
|
||||
logfont.lfPitchAndFamily = fs == FS_MONO ? FIXED_PITCH : VARIABLE_PITCH;
|
||||
logfont.lfCharSet = DEFAULT_CHARSET;
|
||||
logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
|
||||
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
|
||||
if (settings->os_handle != nullptr) {
|
||||
logfont = *(const LOGFONT *)settings->os_handle;
|
||||
} else if (font.find('.') != std::string::npos) {
|
||||
/* Might be a font file name, try load it. */
|
||||
if (!TryLoadFontFromFile(font, logfont)) {
|
||||
ShowInfo("Unable to load file '{}' for {} font, using default windows font selection instead", font, FontSizeToName(fs));
|
||||
}
|
||||
}
|
||||
|
||||
if (logfont.lfFaceName[0] == 0) {
|
||||
logfont.lfWeight = StrContainsIgnoreCase(font, " bold") ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts.
|
||||
convert_to_fs(font, logfont.lfFaceName);
|
||||
}
|
||||
|
||||
LoadWin32Font(fs, logfont, GetFontCacheFontSize(fs), font);
|
||||
}
|
||||
static Win32FontCacheFactory s_win32_fontcache_factory;
|
||||
|
|
|
@ -1036,8 +1036,8 @@ struct GameOptionsWindow : Window {
|
|||
this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite);
|
||||
this->SetDirty();
|
||||
|
||||
InitFontCache(FONTSIZES_ALL);
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::LoadFontCaches(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
CheckForMissingGlyphs();
|
||||
SetupWidgetDimensions();
|
||||
UpdateAllVirtCoords();
|
||||
|
@ -1050,7 +1050,7 @@ struct GameOptionsWindow : Window {
|
|||
this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa);
|
||||
MarkWholeScreenDirty();
|
||||
|
||||
ClearFontCache(FONTSIZES_ALL);
|
||||
FontCache::ClearFontCaches(FONTSIZES_ALL);
|
||||
break;
|
||||
#endif /* HAS_TRUETYPE_FONT */
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "newgrf_text.h"
|
||||
#include "fileio_func.h"
|
||||
#include "signs_base.h"
|
||||
#include "fontdetection.h"
|
||||
#include "error.h"
|
||||
#include "error_func.h"
|
||||
#include "strings_func.h"
|
||||
|
@ -2278,7 +2277,7 @@ std::string_view GetCurrentLanguageIsoCode()
|
|||
*/
|
||||
bool MissingGlyphSearcher::FindMissingGlyphs()
|
||||
{
|
||||
InitFontCache(this->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
FontCache::LoadFontCaches(this->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
|
||||
this->Reset();
|
||||
for (auto text = this->NextString(); text.has_value(); text = this->NextString()) {
|
||||
|
@ -2376,7 +2375,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
|
|||
_fcsettings.mono.os_handle = nullptr;
|
||||
_fcsettings.medium.os_handle = nullptr;
|
||||
|
||||
bad_font = !SetFallbackFont(&_fcsettings, _langpack.langpack->isocode, searcher);
|
||||
bad_font = !FontProviderManager::FindFallbackFont(&_fcsettings, _langpack.langpack->isocode, searcher);
|
||||
|
||||
_fcsettings = std::move(backup);
|
||||
|
||||
|
@ -2395,7 +2394,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
|
|||
/* Our fallback font does miss characters too, so keep the
|
||||
* user chosen font as that is more likely to be any good than
|
||||
* the wild guess we made */
|
||||
InitFontCache(searcher->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
FontCache::LoadFontCaches(searcher->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,8 @@ public:
|
|||
static void InitializeFontCaches()
|
||||
{
|
||||
for (FontSize fs = FS_BEGIN; fs != FS_END; fs++) {
|
||||
if (FontCache::caches[fs] == nullptr) new MockFontCache(fs); /* FontCache inserts itself into to the cache. */
|
||||
if (FontCache::Get(fs) != nullptr) continue;
|
||||
FontCache::Register(std::make_unique<MockFontCache>(fs));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue