Changeset - r10975:551aba2ba975
[Not reviewed]
master
0 1 0
rubidium - 15 years ago 2009-02-02 13:30:13
rubidium@openttd.org
(svn r15314) -Fix/hackaround [FS#2590]: fonts have a feature where they can have localised names. Windows thinks it's a feature to use the name matching the system's locale, Windows doesn't provide an API to get the font name given another locale and freetype uses the English locale to resolve the name when opening the font... This results in fonts that will can't be found and warnings that the fallback font can't be loaded. Work around this by 'manually' getting the non-localised font name from the font.
1 file changed with 79 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/fontcache.cpp
Show inline comments
 
@@ -152,6 +152,84 @@ registry_no_font_found:
 
	return err;
 
}
 

	
 
/**
 
 * Fonts can have localised names and when the system locale is the same as
 
 * one of those localised names Windows will always return that localised name
 
 * instead of allowing to get the non-localised (English US) name of the font.
 
 * This will later on give problems as freetype uses the non-localised name of
 
 * the font and we need to compare based on that name.
 
 * Windows furthermore DOES NOT have an API to get the non-localised name nor
 
 * can we override the system locale. This means that we have to actually read
 
 * the font itself to gather the font name we want.
 
 * Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx
 
 * @param logfont the font information to get the english name of.
 
 * @return the English name (if it could be found).
 
 */
 
static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont)
 
{
 
	static char font_name[MAX_PATH];
 
	const char *ret_font_name = NULL;
 

	
 
	HFONT font = CreateFontIndirect(&logfont->elfLogFont);
 
	if (font == NULL) goto err1;
 

	
 
	HDC dc = GetDC(NULL);
 
	HGDIOBJ oldfont = SelectObject(dc, font);
 
	DWORD dw = GetFontData(dc, 'eman', 0, NULL, 0);
 
	if (dw == GDI_ERROR) goto err2;
 

	
 
	byte *buf = MallocT<byte>(dw);
 
	dw = GetFontData(dc, 'eman', 0, buf, dw);
 
	if (dw == GDI_ERROR) goto err3;
 

	
 
	uint pos = 0;
 
	uint16 format = buf[pos++] << 8;
 
	format += buf[pos++];
 
	assert(format == 0);
 
	uint16 count = buf[pos++] << 8;
 
	count += buf[pos++];
 
	uint16 stringOffset = buf[pos++] << 8;
 
	stringOffset += buf[pos++];
 
	for (uint i = 0; i < count; i++) {
 
		uint16 platformId = buf[pos++] << 8;
 
		platformId += buf[pos++];
 
		uint16 encodingId = buf[pos++] << 8;
 
		encodingId += buf[pos++];
 
		uint16 languageId = buf[pos++] << 8;
 
		languageId += buf[pos++];
 
		uint16 nameId = buf[pos++] << 8;
 
		nameId += buf[pos++];
 
		if (nameId != 1) {
 
			pos += 4; // skip length and offset
 
			continue;
 
		}
 
		uint16 length = buf[pos++] << 8;
 
		length += buf[pos++];
 
		uint16 offset = buf[pos++] << 8;
 
		offset += buf[pos++];
 

	
 
		/* Don't buffer overflow */
 
		length = min(length, MAX_PATH - 1);
 
		for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j];
 
		font_name[length] = '\0';
 

	
 
		if ((platformId == 1 && languageId == 0) ||      // Macintosh English
 
			(platformId == 3 && languageId == 0x0409)) { // Microsoft English (US)
 
			ret_font_name = font_name;
 
			break;
 
		}
 
	}
 

	
 
err3:
 
	free(buf);
 
err2:
 
	SelectObject(dc, oldfont);
 
	ReleaseDC(NULL, dc);
 
err1:
 
	DeleteObject(font);
 

	
 
	return ret_font_name == NULL ? WIDE_TO_MB((const TCHAR*)logfont->elfFullName) : ret_font_name;
 
}
 

	
 
struct EFCParam {
 
	FreeTypeSettings *settings;
 
@@ -184,7 +262,7 @@ static int CALLBACK EnumFontCallback(con
 
		if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) return 1;
 
	}
 

	
 
	const char *font_name = WIDE_TO_MB((const TCHAR*)logfont->elfFullName);
 
	const char *font_name = GetEnglishFontName(logfont);
 
	DEBUG(freetype, 1, "Fallback font: %s", font_name);
 

	
 
	strecpy(info->settings->small_font,  font_name, lastof(info->settings->small_font));
0 comments (0 inline, 0 general)