Changeset - r24651:d256fd14817f
[Not reviewed]
master
0 3 0
Patric Stout - 3 years ago 2021-01-12 18:52:30
truebrain@openttd.org
Codechange: nobody was using "str" parameter, so remove it
3 files changed with 8 insertions and 11 deletions:
0 comments (0 inline, 0 general)
src/fontdetection.cpp
Show inline comments
 
@@ -326,49 +326,49 @@ static int CALLBACK EnumFontCallback(con
 

	
 
	/* Check whether we can actually load the font. */
 
	bool ft_init = _library != nullptr;
 
	bool found = false;
 
	FT_Face face;
 
	/* Init FreeType if needed. */
 
	if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName(font_name, &face) == FT_Err_Ok) {
 
		FT_Done_Face(face);
 
		found = true;
 
	}
 
	if (!ft_init) {
 
		/* Uninit FreeType if we did the init. */
 
		FT_Done_FreeType(_library);
 
		_library = nullptr;
 
	}
 

	
 
	if (!found) return 1;
 
#else
 
	const char *english_name = font_name;
 
#endif /* WITH_FREETYPE */
 

	
 
	PLOGFONT os_data = MallocT<LOGFONT>(1);
 
	*os_data = logfont->elfLogFont;
 
	info->callback->SetFontNames(info->settings, font_name, os_data);
 
	if (info->callback->FindMissingGlyphs(nullptr)) return 1;
 
	if (info->callback->FindMissingGlyphs()) return 1;
 
	DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name);
 
	return 0; // stop enumerating
 
}
 

	
 
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
 
{
 
	DEBUG(freetype, 1, "Trying fallback fonts");
 
	EFCParam langInfo;
 
	if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, sizeof(langInfo.locale) / sizeof(TCHAR)) == 0) {
 
		/* Invalid langid or some other mysterious error, can't determine fallback font. */
 
		DEBUG(freetype, 1, "Can't get locale info for fallback font (langid=0x%x)", winlangid);
 
		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);
 
@@ -456,63 +456,63 @@ bool SetFallbackFont(FreeTypeSettings *s
 

	
 
		/* 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 name[128];
 
		CFAutoRelease<CFStringRef> font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute));
 
		CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8);
 

	
 
		/* There are some special fonts starting with an '.' and the last
 
		 * resort font that aren't usable. Skip them. */
 
		if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue;
 

	
 
		/* Save result. */
 
		callback->SetFontNames(settings, name);
 
		if (!callback->FindMissingGlyphs(nullptr)) {
 
		if (!callback->FindMissingGlyphs()) {
 
			DEBUG(freetype, 2, "CT-Font for %s: %s", 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(nullptr);
 
		result = !callback->FindMissingGlyphs();
 
	}
 

	
 
	callback->FindMissingGlyphs(nullptr);
 
	callback->FindMissingGlyphs();
 
	return result;
 
}
 

	
 
#elif defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */
 

	
 
#include <fontconfig/fontconfig.h>
 

	
 
#include "safeguards.h"
 

	
 
/* ========================================================================================
 
 * FontConfig (unix) support
 
 * ======================================================================================== */
 
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
 
{
 
	FT_Error err = FT_Err_Cannot_Open_Resource;
 

	
 
	if (!FcInit()) {
 
		ShowInfoF("Unable to load font configuration");
 
	} else {
 
		FcPattern *match;
 
		FcPattern *pat;
 
		FcFontSet *fs;
 
		FcResult  result;
 
		char *font_style;
 
@@ -602,49 +602,49 @@ bool SetFallbackFont(FreeTypeSettings *s
 
		for (int i = 0; i < fs->nfont; i++) {
 
			FcPattern *font = fs->fonts[i];
 

	
 
			FcChar8 *file = nullptr;
 
			FcResult res = FcPatternGetString(font, FC_FILE, 0, &file);
 
			if (res != FcResultMatch || file == nullptr) {
 
				continue;
 
			}
 

	
 
			/* Get a font with the right spacing .*/
 
			int value = 0;
 
			FcPatternGetInteger(font, FC_SPACING, 0, &value);
 
			if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue;
 

	
 
			/* Do not use those that explicitly say they're slanted. */
 
			FcPatternGetInteger(font, FC_SLANT, 0, &value);
 
			if (value != 0) continue;
 

	
 
			/* We want the fatter font as they look better at small sizes. */
 
			FcPatternGetInteger(font, FC_WEIGHT, 0, &value);
 
			if (value <= best_weight) continue;
 

	
 
			callback->SetFontNames(settings, (const char*)file);
 

	
 
			bool missing = callback->FindMissingGlyphs(nullptr);
 
			bool missing = callback->FindMissingGlyphs();
 
			DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");
 

	
 
			if (!missing) {
 
				best_weight = value;
 
				best_font   = (const char *)file;
 
			}
 
		}
 

	
 
		if (best_font != nullptr) {
 
			ret = true;
 
			callback->SetFontNames(settings, best_font);
 
			InitFreeType(callback->Monospace());
 
		}
 

	
 
		/* Clean up the list of filenames. */
 
		FcFontSetDestroy(fs);
 
	}
 

	
 
	FcFini();
 
	return ret;
 
}
 

	
 
#else /* without WITH_FONTCONFIG */
 
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;}
src/strings.cpp
Show inline comments
 
@@ -1977,65 +1977,62 @@ void InitializeLanguagePacks()
 
		if (strncmp(lng.isocode, lang, 5) == 0) chosen_language   = &lng;
 
		if (strncmp(lng.isocode, lang, 2) == 0) language_fallback = &lng;
 
	}
 

	
 
	/* We haven't found the language in the config nor the one in the locale.
 
	 * Now we set it to one of the fallback languages */
 
	if (chosen_language == nullptr) {
 
		chosen_language = (language_fallback != nullptr) ? language_fallback : en_GB_fallback;
 
	}
 

	
 
	if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", chosen_language->file);
 
}
 

	
 
/**
 
 * Get the ISO language code of the currently loaded language.
 
 * @return the ISO code.
 
 */
 
const char *GetCurrentLanguageIsoCode()
 
{
 
	return _langpack.langpack->isocode;
 
}
 

	
 
/**
 
 * Check whether there are glyphs missing in the current language.
 
 * @param[out] str Pointer to an address for storing the text pointer.
 
 * @return If glyphs are missing, return \c true, else return \c false.
 
 * @post If \c true is returned and str is not nullptr, *str points to a string that is found to contain at least one missing glyph.
 
 */
 
bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
 
bool MissingGlyphSearcher::FindMissingGlyphs()
 
{
 
	InitFreeType(this->Monospace());
 
	const Sprite *question_mark[FS_END];
 

	
 
	for (FontSize size = this->Monospace() ? FS_MONO : FS_BEGIN; size < (this->Monospace() ? FS_END : FS_MONO); size++) {
 
		question_mark[size] = GetGlyph(size, '?');
 
	}
 

	
 
	this->Reset();
 
	for (const char *text = this->NextString(); text != nullptr; text = this->NextString()) {
 
		FontSize size = this->DefaultSize();
 
		if (str != nullptr) *str = text;
 
		for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
 
			if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
 
				size = (FontSize)(c - SCC_FIRST_FONT);
 
			} else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
 
				/* The character is printable, but not in the normal font. This is the case we were testing for. */
 
				return true;
 
			}
 
		}
 
	}
 
	return false;
 
}
 

	
 
/** Helper for searching through the language pack. */
 
class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
 
	uint i; ///< Iterator for the primary language tables.
 
	uint j; ///< Iterator for the secondary language tables.
 

	
 
	void Reset() override
 
	{
 
		this->i = 0;
 
		this->j = 0;
 
	}
 

	
 
	FontSize DefaultSize() override
 
@@ -2074,49 +2071,49 @@ class LanguagePackGlyphSearcher : public
 
		settings->small.os_handle = os_data;
 
		settings->medium.os_handle = os_data;
 
		settings->large.os_handle = os_data;
 
#endif
 
	}
 
};
 

	
 
/**
 
 * Check whether the currently loaded language pack
 
 * uses characters that the currently loaded font
 
 * does not support. If this is the case an error
 
 * message will be shown in English. The error
 
 * message will not be localized because that would
 
 * mean it might use characters that are not in the
 
 * font, which is the whole reason this check has
 
 * been added.
 
 * @param base_font Whether to look at the base font as well.
 
 * @param searcher  The methods to use to search for strings to check.
 
 *                  If nullptr the loaded language pack searcher is used.
 
 */
 
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
 
{
 
	static LanguagePackGlyphSearcher pack_searcher;
 
	if (searcher == nullptr) searcher = &pack_searcher;
 
	bool bad_font = !base_font || searcher->FindMissingGlyphs(nullptr);
 
	bool bad_font = !base_font || searcher->FindMissingGlyphs();
 
#if defined(WITH_FREETYPE) || defined(_WIN32)
 
	if (bad_font) {
 
		/* We found an unprintable character... lets try whether we can find
 
		 * a fallback font that can print the characters in the current language. */
 
		FreeTypeSettings backup;
 
		memcpy(&backup, &_freetype, sizeof(backup));
 

	
 
		_freetype.mono.os_handle = nullptr;
 
		_freetype.medium.os_handle = nullptr;
 

	
 
		bad_font = !SetFallbackFont(&_freetype, _langpack.langpack->isocode, _langpack.langpack->winlangid, searcher);
 

	
 
		free(_freetype.mono.os_handle);
 
		free(_freetype.medium.os_handle);
 

	
 
		memcpy(&_freetype, &backup, sizeof(backup));
 

	
 
		if (bad_font && base_font) {
 
			/* 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 */
 
			InitFreeType(searcher->Monospace());
 
		}
 
	}
src/strings_func.h
Show inline comments
 
@@ -256,30 +256,30 @@ public:
 
	 * Get the default (font) size of the string.
 
	 * @return The font size.
 
	 */
 
	virtual FontSize DefaultSize() = 0;
 

	
 
	/**
 
	 * Reset the search, i.e. begin from the beginning again.
 
	 */
 
	virtual void Reset() = 0;
 

	
 
	/**
 
	 * Whether to search for a monospace font or not.
 
	 * @return True if searching for monospace.
 
	 */
 
	virtual bool Monospace() = 0;
 

	
 
	/**
 
	 * Set the right font names.
 
	 * @param settings  The settings to modify.
 
	 * @param font_name The new font name.
 
	 * @param os_data Opaque pointer to OS-specific data.
 
	 */
 
	virtual void SetFontNames(struct FreeTypeSettings *settings, const char *font_name, const void *os_data = nullptr) = 0;
 

	
 
	bool FindMissingGlyphs(const char **str);
 
	bool FindMissingGlyphs();
 
};
 

	
 
void CheckForMissingGlyphs(bool base_font = true, MissingGlyphSearcher *search = nullptr);
 

	
 
#endif /* STRINGS_FUNC_H */
0 comments (0 inline, 0 general)