(svn r7337) -Feature: [win32] Add font selection by specifying a font-name, ala Fontconfig. Pretty

messy if you ask me, but this is what you get when MS hides the font API in the deepest
 depths... thanks Rubidium for testing.
This commit is contained in:
Darkvater
2006-12-03 19:03:38 +00:00
parent 0074c82912
commit dcd95059be
2 changed files with 174 additions and 65 deletions

View File

@@ -34,23 +34,104 @@ enum {
SHADOW_COLOUR = 2,
};
#ifdef WIN32
#include <windows.h>
#include <tchar.h>
#include <shlobj.h> // SHGetFolderPath
#include "win32.h"
/**
* 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'.
*/
static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *type)
#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
#define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts"
static FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
{
FT_Error error;
FT_Error err = FT_Err_Cannot_Open_Resource;
HKEY hKey;
LONG ret;
TCHAR vbuffer[MAX_PATH], dbuffer[256];
char *font_path;
uint index;
if (strlen(font_name) == 0) return;
/* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the
* "Windows NT" key, on Windows 9x in the Windows key. To save us having
* to retrieve the windows version, we'll just query both */
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey);
if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey);
error = FT_New_Face(_library, font_name, 0, face);
if (ret != ERROR_SUCCESS) {
DEBUG(freetype, 0) ("Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
return err;
}
for (index = 0;; index++) {
char *s;
DWORD vbuflen = lengthof(vbuffer);
DWORD dbuflen = lengthof(dbuffer);
ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, NULL, NULL, dbuffer, &dbuflen);
if (ret != ERROR_SUCCESS) break;
/* The font names in the registry are of the following 3 forms:
* - ADMUI3.fon
* - Book Antiqua Bold (TrueType)
* - Batang & BatangChe & Gungsuh & GungsuhChe (TrueType)
* We will strip the font-type '()' if any and work with the font name
* itself, which must match exactly; if...
* TTC files, font files which contain more than one font are seperated
* byt '&'. Our best bet will be to do substr match for the fontname
* and then let FreeType figure out which index to load */
s = _tcschr(vbuffer, '(');
if (s != NULL) s[-1] = '\0';
if (_tcschr(vbuffer, '&') == NULL) {
if (_tcsicmp(vbuffer, font_name) == 0) break;
} else {
if (_tcsstr(vbuffer, font_name) != NULL) break;
}
}
if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) {
DEBUG(freetype, 0) ("SHGetFolderPath cannot return fonts directory");
goto folder_error;
}
/* Some fonts are contained in .ttc files, TrueType Collection fonts. These
* contain multiple fonts inside this single file. GetFontData however
* returns the whole file, so we need to check each font inside to get the
* proper font. If not found, we will use the last font in the ttc.
* Also note that FreeType does not support UNICODE filesnames! */
#if defined(UNICODE)
font_path = malloc(MAX_PATH);
font_path = convert_from_fs(vbuffer, font_path, MAX_PATH);
#else
font_path = vbuffer;
#endif
ttd_strlcat(font_path, "\\", MAX_PATH);
ttd_strlcat(font_path, WIDE_TO_MB(dbuffer), MAX_PATH);
index = 0;
do {
err = FT_New_Face(_library, font_path, index, face);
if (err != FT_Err_Ok) break;
if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
err = FT_Err_Cannot_Open_Resource;
} while ((FT_Long)++index != (*face)->num_faces);
#if defined(UNICODE)
free(font_path);
#endif
folder_error:
RegCloseKey(hKey);
return err;
}
#else
# ifdef WITH_FONTCONFIG
/* Failed to load the font, so try it with fontconfig */
if (error != FT_Err_Ok) {
static 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 {
@@ -85,7 +166,7 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t
FcChar8 *file;
FcFontSetAdd(fs, match);
for (i = 0; error != FT_Err_Ok && i < fs->nfont; i++) {
for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) {
/* Try the new filename */
if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch &&
FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch &&
@@ -98,7 +179,7 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t
* wrongly a 'random' font, so check whether the family name is the
* same as the supplied name */
if (strcasecmp(font_family, (char*)family) == 0) {
error = FT_New_Face(_library, (char *)file, 0, face);
err = FT_New_Face(_library, (char *)file, 0, face);
}
}
}
@@ -109,15 +190,39 @@ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *t
FcFontSetDestroy(fs);
FcFini();
}
return err;
}
# else
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;}
# endif /* WITH_FONTCONFIG */
#endif
/**
* 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'.
*/
static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *type)
{
FT_Error error;
if (strlen(font_name) == 0) return;
error = FT_New_Face(_library, font_name, 0, face);
if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, face);
if (error == FT_Err_Ok) {
DEBUG(freetype, 2) ("Requested font '%s', found '%s %s'", font_name, (*face)->family_name, (*face)->style_name);
/* Attempt to select the unicode character map */
error = FT_Select_Charmap(*face, ft_encoding_unicode);
if (error == FT_Err_Ok) {
/* Success */
return;
} else if (error == FT_Err_Invalid_CharMap_Handle) {
if (error == FT_Err_Ok) return; // 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...) */

View File

@@ -23,4 +23,8 @@ wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen);
# define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str)
#endif
#if defined(__MINGW32__)
#define SHGFP_TYPE_CURRENT 0
#endif /* __MINGW32__ */
#endif /* WIN32_H */