changeset 18423:fe86a6bfde45 draft

(svn r23265) -Codechange: replace the setfallbackfont callback function with a class to call back
author rubidium <rubidium@openttd.org>
date Sat, 19 Nov 2011 18:43:00 +0000
parents 470aeadadd91
children aeb8d6b635a1
files src/fontcache.cpp src/fontcache.h src/strings.cpp src/strings_func.h
diffstat 4 files changed, 96 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/fontcache.cpp
+++ b/src/fontcache.cpp
@@ -13,6 +13,7 @@
 #include "fontcache.h"
 #include "blitter/factory.hpp"
 #include "core/math_func.hpp"
+#include "strings_func.h"
 
 #include "table/sprites.h"
 #include "table/control_codes.h"
@@ -289,7 +290,7 @@
 struct EFCParam {
 	FreeTypeSettings *settings;
 	LOCALESIGNATURE  locale;
-	SetFallbackFontCallback *callback;
+	MissingGlyphSearcher *callback;
 };
 
 static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam)
@@ -349,12 +350,12 @@
 	strecpy(info->settings->small_font,  font_name, lastof(info->settings->small_font));
 	strecpy(info->settings->medium_font, font_name, lastof(info->settings->medium_font));
 	strecpy(info->settings->large_font,  font_name, lastof(info->settings->large_font));
-	if (info->callback(NULL)) return 1;
+	if (info->callback->FindMissingGlyphs(NULL)) 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, SetFallbackFontCallback *callback)
+bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
 {
 	DEBUG(freetype, 1, "Trying fallback fonts");
 	EFCParam langInfo;
@@ -428,12 +429,12 @@
 	return err;
 }
 
-bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, SetFallbackFontCallback *callback)
+bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
 {
 	const char *str;
 	bool result = false;
 
-	callback(&str);
+	callback->FindMissingGlyphs(&str);
 
 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
 	if (MacOSVersionIsAtLeast(10, 5, 0)) {
@@ -609,7 +610,7 @@
 		}
 	 }
 
-	callback(NULL);
+	callback->FindMissingGlyphs(NULL);
 	return result;
 }
 
@@ -683,7 +684,7 @@
 	return err;
 }
 
-bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, SetFallbackFontCallback *callback)
+bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
 {
 	if (!FcInit()) return false;
 
@@ -722,7 +723,7 @@
 			strecpy(settings->medium_font, (const char*)file, lastof(settings->medium_font));
 			strecpy(settings->large_font,  (const char*)file, lastof(settings->large_font));
 
-			bool missing = callback(NULL);
+			bool missing = callback->FindMissingGlyphs(NULL);
 			DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");
 
 			if (!missing) {
@@ -741,7 +742,7 @@
 
 #else /* without WITH_FONTCONFIG */
 FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;}
-bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, SetFallbackFontCallback *callback) { return false; }
+bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; }
 #endif /* WITH_FONTCONFIG */
 
 static void SetFontGeometry(FT_Face face, FontSize size, int pixels)
--- a/src/fontcache.h
+++ b/src/fontcache.h
@@ -47,7 +47,6 @@
 uint GetGlyphWidth(FontSize size, uint32 key);
 bool GetDrawGlyphShadow();
 
-typedef bool (SetFallbackFontCallback)(const char **);
 /**
  * We would like to have a fallback font as the current one
  * doesn't contain all characters we need.
@@ -58,7 +57,7 @@
  * @param callback The function to call to check for missing glyphs.
  * @return true if a font has been set, false otherwise.
  */
-bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, SetFallbackFontCallback *callback);
+bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, class MissingGlyphSearcher *callback);
 
 #else
 
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -1750,46 +1750,75 @@
  * @return If glyphs are missing, return \c true, else return \false.
  * @post If \c true is returned and str is not NULL, *str points to a string that is found to contain at least one missing glyph.
  */
-static bool FindMissingGlyphs(const char **str)
+bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
 {
 #ifdef WITH_FREETYPE
 	UninitFreeType();
 	InitFreeType();
 #endif
 	const Sprite *question_mark[FS_END];
-	FontSize size;
 
-	for (size = FS_BEGIN; size < FS_END; size++) {
+	for (FontSize size = FS_BEGIN; size < FS_END; size++) {
 		question_mark[size] = GetGlyph(size, '?');
 	}
 
-	for (uint i = 0; i != 32; i++) {
-		for (uint j = 0; j < _langtab_num[i]; j++) {
-			size = FS_NORMAL;
-			const char *text = _langpack_offs[_langtab_start[i] + j];
-			if (str != NULL) *str = text;
-			for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
-				if (c == SCC_SETX) {
-					/* SetX is, together with SetXY as special character that
-					 * uses the next (two) characters as data points. We have
-					 * to skip those, otherwise the UTF8 reading will go haywire. */
-					text++;
-				} else if (c == SCC_SETXY) {
-					text += 2;
-				} else if (c == SCC_TINYFONT) {
-					size = FS_SMALL;
-				} else if (c == SCC_BIGFONT) {
-					size = FS_LARGE;
-				} 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;
-				}
+	this->Reset();
+	for (const char *text = this->NextString(); text != NULL; text = this->NextString()) {
+		FontSize size = this->DefaultSize();
+		if (str != NULL) *str = text;
+		for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
+			if (c == SCC_SETX) {
+				/* SetX is, together with SetXY as special character that
+					* uses the next (two) characters as data points. We have
+					* to skip those, otherwise the UTF8 reading will go haywire. */
+				text++;
+			} else if (c == SCC_SETXY) {
+				text += 2;
+			} else if (c == SCC_TINYFONT) {
+				size = FS_SMALL;
+			} else if (c == SCC_BIGFONT) {
+				size = FS_LARGE;
+			} 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.
+
+	/* virtual */ void Reset()
+	{
+		this->i = 0;
+		this->j = 0;
+	}
+
+	FontSize DefaultSize()
+	{
+		return FS_NORMAL;
+	}
+
+	const char *NextString()
+	{
+		if (this->i >= 32) return NULL;
+
+		const char *ret = _langpack_offs[_langtab_start[i] + j];
+
+		this->j++;
+		while (this->j >= _langtab_num[this->i] && this->i < 32) {
+			i++;
+			j = 0;
+		}
+
+		return ret;
+	}
+};
+
 /**
  * Check whether the currently loaded language pack
  * uses characters that the currently loaded font
@@ -1803,7 +1832,8 @@
  */
 void CheckForMissingGlyphsInLoadedLanguagePack(bool base_font)
 {
-	bool bad_font = !base_font || FindMissingGlyphs(NULL);
+	LanguagePackGlyphSearcher searcher;
+	bool bad_font = !base_font || searcher.FindMissingGlyphs(NULL);
 #ifdef WITH_FREETYPE
 	if (bad_font) {
 		/* We found an unprintable character... lets try whether we can find
@@ -1811,7 +1841,7 @@
 		FreeTypeSettings backup;
 		memcpy(&backup, &_freetype, sizeof(backup));
 
-		bad_font = !SetFallbackFont(&_freetype, _langpack->isocode, _langpack->winlangid, &FindMissingGlyphs);
+		bad_font = !SetFallbackFont(&_freetype, _langpack->isocode, _langpack->winlangid, &searcher);
 
 		memcpy(&_freetype, &backup, sizeof(backup));
 
--- a/src/strings_func.h
+++ b/src/strings_func.h
@@ -14,6 +14,7 @@
 
 #include "strings_type.h"
 #include "string_type.h"
+#include "gfx_type.h"
 
 class StringParameters {
 	StringParameters *parent; ///< If not NULL, this instance references data from this parent instance.
@@ -196,6 +197,34 @@
 
 int CDECL StringIDSorter(const StringID *a, const StringID *b);
 
+/**
+ * A searcher for missing glyphs.
+ */
+class MissingGlyphSearcher {
+public:
+	/** Make sure everything gets destructed right. */
+	virtual ~MissingGlyphSearcher() {}
+
+	/**
+	 * Get the next string to search through.
+	 * @return The next string or NULL if there is none.
+	 */
+	virtual const char *NextString() = 0;
+
+	/**
+	 * 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;
+
+	bool FindMissingGlyphs(const char **str);
+};
+
 void CheckForMissingGlyphsInLoadedLanguagePack(bool base_font = true);
 
 #endif /* STRINGS_FUNC_H */