Add support for bitmap fonts.

This commit is contained in:
Huw Davies 2004-06-16 20:06:26 +00:00 committed by Alexandre Julliard
parent 554606d241
commit c22171836b
5 changed files with 538 additions and 248 deletions

2
configure vendored
View File

@ -10541,6 +10541,7 @@ fi
for ac_header in ft2build.h \ for ac_header in ft2build.h \
freetype/freetype.h \ freetype/freetype.h \
freetype/ftglyph.h \ freetype/ftglyph.h \
@ -10549,6 +10550,7 @@ for ac_header in ft2build.h \
freetype/ftsnames.h \ freetype/ftsnames.h \
freetype/ttnameid.h \ freetype/ttnameid.h \
freetype/ftoutln.h \ freetype/ftoutln.h \
freetype/ftwinfnt.h \
freetype/internal/sfnt.h freetype/internal/sfnt.h
do do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`

View File

@ -461,6 +461,7 @@ else
freetype/ftsnames.h \ freetype/ftsnames.h \
freetype/ttnameid.h \ freetype/ttnameid.h \
freetype/ftoutln.h \ freetype/ftoutln.h \
freetype/ftwinfnt.h \
freetype/internal/sfnt.h,,, freetype/internal/sfnt.h,,,
[#if HAVE_FT2BUILD_H [#if HAVE_FT2BUILD_H
#include <ft2build.h> #include <ft2build.h>

View File

@ -76,6 +76,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(font);
#ifdef HAVE_FREETYPE_FTTRIGON_H #ifdef HAVE_FREETYPE_FTTRIGON_H
#include <freetype/fttrigon.h> #include <freetype/fttrigon.h>
#endif #endif
#ifdef HAVE_FREETYPE_FTWINFNT_H
#include <freetype/ftwinfnt.h>
#endif
#ifndef SONAME_LIBFREETYPE #ifndef SONAME_LIBFREETYPE
#define SONAME_LIBFREETYPE "libfreetype.so" #define SONAME_LIBFREETYPE "libfreetype.so"
@ -89,6 +92,7 @@ typedef struct
FT_Int patch; FT_Int patch;
} FT_Version_t; } FT_Version_t;
static FT_Version_t FT_Version; static FT_Version_t FT_Version;
static DWORD FT_SimpleVersion;
static void *ft_handle = NULL; static void *ft_handle = NULL;
@ -111,6 +115,9 @@ MAKE_FUNCPTR(FT_Vector_Transform);
static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*); static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*); static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*); static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*);
#ifdef HAVE_FREETYPE_FTWINFNT_H
MAKE_FUNCPTR(FT_Get_WinFNT_Header);
#endif
#ifdef HAVE_FONTCONFIG_FONTCONFIG_H #ifdef HAVE_FONTCONFIG_FONTCONFIG_H
#include <fontconfig/fontconfig.h> #include <fontconfig/fontconfig.h>
@ -134,6 +141,16 @@ MAKE_FUNCPTR(FcPatternGet);
#define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] ) #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
/* This is bascially a copy of FT_Bitmap_Size with an extra element added */
typedef struct {
FT_Short height;
FT_Short width;
FT_Pos size;
FT_Pos x_ppem;
FT_Pos y_ppem;
FT_Short internal_leading;
} Bitmap_Size;
typedef struct tagFace { typedef struct tagFace {
WCHAR *StyleName; WCHAR *StyleName;
char *file; char *file;
@ -142,6 +159,8 @@ typedef struct tagFace {
BOOL Bold; BOOL Bold;
FONTSIGNATURE fs; FONTSIGNATURE fs;
FT_Fixed font_version; FT_Fixed font_version;
BOOL scalable;
Bitmap_Size size; /* set if face is a bitmap */
BOOL external; /* TRUE if we should manually add this font to the registry */ BOOL external; /* TRUE if we should manually add this font to the registry */
struct tagFace *next; struct tagFace *next;
struct tagFamily *family; struct tagFamily *family;
@ -198,6 +217,7 @@ static const WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ',
static const WCHAR HelvW[] = {'H','e','l','v','\0'}; static const WCHAR HelvW[] = {'H','e','l','v','\0'};
static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'}; static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'};
static const WCHAR fontsW[] = {'\\','F','o','n','t','s','\0'};
static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\', 'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
@ -208,6 +228,18 @@ static const WCHAR winnt_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'F','o','n','t','s','\0'}; 'F','o','n','t','s','\0'};
static const WCHAR system_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
static const WCHAR FixedSys_Value[] = {'F','I','X','E','D','F','O','N','.','F','O','N','\0'};
static const WCHAR System_Value[] = {'F','O','N','T','S','.','F','O','N','\0'};
static const WCHAR OEMFont_Value[] = {'O','E','M','F','O','N','T','.','F','O','N','\0'};
static const WCHAR *SystemFontValues[4] = {
FixedSys_Value,
System_Value,
OEMFont_Value,
NULL
};
static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','W','i','n','e','\\', static const WCHAR external_fonts_reg_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','W','i','n','e','\\',
'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'}; 'F','o','n','t','s','\\','E','x','t','e','r','n','a','l',' ','F','o','n','t','s','\0'};
@ -228,6 +260,7 @@ static const WCHAR ThaiW[] = {'T','h','a','i','\0'};
static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'}; static const WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'}; static const WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'};
static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'}; static const WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'};
static const WCHAR OEM_DOSW[] = {'O','E','M','/','D','O','S','\0'};
static const WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */ static const WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */
WesternW, /*00*/ WesternW, /*00*/
@ -267,6 +300,38 @@ static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail i
static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'}; static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'};
/****************************************
* Notes on .fon files
*
* The fonts System, FixedSys and Terminal are special. There are typically multiple
* versions installed for different resolutions and codepages. Windows stores which one to use
* in HKEY_CURRENT_CONFIG\\Software\\Fonts.
* Key Meaning
* FIXEDFON.FON FixedSys
* FONTS.FON System
* OEMFONT.FON Termial
* LogPixels Current dpi set by the display control panel applet
* (HKLM\\Software\\Microsft\\Windows NT\\CurrentVersion\\FontDPI
* also has a LogPixels value that appears to mirror this)
*
* On my system these values have data: vgafix.fon, vgasys.fon, vga850.fon and 96 respectively
* (vgaoem.fon would be your oemfont.fon if you have a US setup).
* If the resolution is changed to be >= 109dpi then the fonts goto 8514fix, 8514sys and 8514oem
* (not sure what's happening to the oem codepage here). 109 is nicely halfway between 96 and 120dpi,
* so that makes sense.
*
* Additionally Windows also loads the fonts listed in the [386enh] section of system.ini (this doesn't appear
* to be mapped into the registry on Windows 2000 at least).
* I have
* woafont=app850.fon
* ega80woa.fon=ega80850.fon
* ega40woa.fon=ega40850.fon
* cga80woa.fon=cga80850.fon
* cga40woa.fon=cga40850.fon
*/
static inline BOOL is_win9x(void) static inline BOOL is_win9x(void)
{ {
return GetVersion() & 0x80000000; return GetVersion() & 0x80000000;
@ -292,19 +357,23 @@ static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract); return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
} }
static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external_font) #define ADDFONT_EXTERNAL_FONT 0x01
#define ADDFONT_FORCE_BITMAP 0x02
static BOOL AddFontFileToList(const char *file, char *fake_family, DWORD flags)
{ {
FT_Face ft_face; FT_Face ft_face;
TT_OS2 *pOS2; TT_OS2 *pOS2;
TT_Header *pHeader; TT_Header *pHeader = NULL;
WCHAR *FamilyW, *StyleW; WCHAR *FamilyW, *StyleW;
DWORD len; DWORD len;
Family *family = FontList; Family **pfamily;
Family **insert = &FontList;
Face **insertface, *next; Face **insertface, *next;
FT_Error err; FT_Error err;
FT_Long face_index = 0, num_faces; FT_Long face_index = 0, num_faces;
int i; #ifdef HAVE_FREETYPE_FTWINFNT_H
FT_WinFNT_HeaderRec winfnt_header;
#endif
int i, bitmap_num;
do { do {
char *family_name = fake_family; char *family_name = fake_family;
@ -315,13 +384,20 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
return FALSE; return FALSE;
} }
if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */ if(!FT_IS_SFNT(ft_face) && (FT_IS_SCALABLE(ft_face) || !(flags & ADDFONT_FORCE_BITMAP))) { /* for now we'll accept TT/OT or bitmap fonts*/
pFT_Done_Face(ft_face); pFT_Done_Face(ft_face);
return FALSE; return FALSE;
} }
if(!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
/* There are too many bugs in FreeType < 2.1.9 for bitmap font support */
if(!FT_IS_SCALABLE(ft_face) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) {
pFT_Done_Face(ft_face);
return FALSE;
}
if(FT_IS_SFNT(ft_face) && (!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) || !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea) ||
!(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head))) { !(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head)))) {
TRACE("Font file %s lacks either an OS2, HHEA or HEAD table.\n" TRACE("Font file %s lacks either an OS2, HHEA or HEAD table.\n"
"Skipping this font.\n", debugstr_a(file)); "Skipping this font.\n", debugstr_a(file));
pFT_Done_Face(ft_face); pFT_Done_Face(ft_face);
@ -337,21 +413,23 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
if(!family_name) if(!family_name)
family_name = ft_face->family_name; family_name = ft_face->family_name;
bitmap_num = 0;
do {
len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0); len = MultiByteToWideChar(CP_ACP, 0, family_name, -1, NULL, 0);
FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len); MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len);
while(family) { pfamily = &FontList;
if(!strcmpW(family->FamilyName, FamilyW)) while(*pfamily) {
if(!strcmpW((*pfamily)->FamilyName, FamilyW))
break; break;
insert = &family->next; pfamily = &(*pfamily)->next;
family = family->next;
} }
if(!family) { if(!*pfamily) {
family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family)); *pfamily = HeapAlloc(GetProcessHeap(), 0, sizeof(**pfamily));
family->FamilyName = FamilyW; (*pfamily)->FamilyName = FamilyW;
family->FirstFace = NULL; (*pfamily)->FirstFace = NULL;
family->next = NULL; (*pfamily)->next = NULL;
} else { } else {
HeapFree(GetProcessHeap(), 0, FamilyW); HeapFree(GetProcessHeap(), 0, FamilyW);
} }
@ -361,11 +439,11 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len); MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
next = NULL; next = NULL;
for(insertface = &family->FirstFace; *insertface; for(insertface = &(*pfamily)->FirstFace; *insertface;
insertface = &(*insertface)->next) { insertface = &(*insertface)->next) {
if(!strcmpW((*insertface)->StyleName, StyleW)) { if(!strcmpW((*insertface)->StyleName, StyleW) && FT_IS_SCALABLE(ft_face)) {
TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n", TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
debugstr_w(family->FamilyName), debugstr_w(StyleW), debugstr_w((*pfamily)->FamilyName), debugstr_w(StyleW),
(*insertface)->font_version, pHeader->Font_Revision); (*insertface)->font_version, pHeader->Font_Revision);
if(fake_family) { if(fake_family) {
@ -397,9 +475,37 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
(*insertface)->next = next; (*insertface)->next = next;
(*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0; (*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
(*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0; (*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
(*insertface)->font_version = pHeader->Font_Revision; (*insertface)->font_version = pHeader ? pHeader->Font_Revision : 0;
(*insertface)->family = family; (*insertface)->family = *pfamily;
(*insertface)->external = external_font; (*insertface)->external = (flags & ADDFONT_EXTERNAL_FONT) ? TRUE : FALSE;
if(FT_IS_SCALABLE(ft_face)) {
memset(&(*insertface)->size, 0, sizeof((*insertface)->size));
(*insertface)->scalable = TRUE;
} else {
/* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
So to let this compile on older versions of FreeType we'll define the
new structure here. Note that this code is never executed when run with
earlier versions of the library because of the version check above */
struct my_bitmap_size {
FT_Short height, width;
FT_Pos size, x_ppem, y_ppem;
} *size;
size = (struct my_bitmap_size *)ft_face->available_sizes + bitmap_num;
TRACE("Adding bitmap size h %d w %d size %ld x_ppem %ld y_ppem %ld\n",
size->height, size->width, size->size >> 6,
size->x_ppem >> 6, size->y_ppem >> 6);
(*insertface)->size.height = size->height;
(*insertface)->size.width = size->width;
(*insertface)->size.size = size->size;
(*insertface)->size.x_ppem = size->x_ppem;
(*insertface)->size.y_ppem = size->y_ppem;
(*insertface)->size.internal_leading = 0;
(*insertface)->scalable = FALSE;
}
memset(&(*insertface)->fs, 0, sizeof((*insertface)->fs));
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
if(pOS2) { if(pOS2) {
@ -409,27 +515,30 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
(*insertface)->fs.fsUsb[1] = pOS2->ulUnicodeRange2; (*insertface)->fs.fsUsb[1] = pOS2->ulUnicodeRange2;
(*insertface)->fs.fsUsb[2] = pOS2->ulUnicodeRange3; (*insertface)->fs.fsUsb[2] = pOS2->ulUnicodeRange3;
(*insertface)->fs.fsUsb[3] = pOS2->ulUnicodeRange4; (*insertface)->fs.fsUsb[3] = pOS2->ulUnicodeRange4;
} else {
(*insertface)->fs.fsCsb[0] = (*insertface)->fs.fsCsb[1] = 0;
(*insertface)->fs.fsUsb[0] = 0;
(*insertface)->fs.fsUsb[1] = 0;
(*insertface)->fs.fsUsb[2] = 0;
(*insertface)->fs.fsUsb[3] = 0;
}
TRACE("fsCsb = %08lx %08lx/%08lx %08lx %08lx %08lx\n",
(*insertface)->fs.fsCsb[0], (*insertface)->fs.fsCsb[1],
(*insertface)->fs.fsUsb[0], (*insertface)->fs.fsUsb[1],
(*insertface)->fs.fsUsb[2], (*insertface)->fs.fsUsb[3]);
if(pOS2->version == 0) { if(pOS2->version == 0) {
FT_UInt dummy; FT_UInt dummy;
/* If the function is not there, we assume the font is ok */
if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100)) if(!pFT_Get_First_Char || (pFT_Get_First_Char( ft_face, &dummy ) < 0x100))
(*insertface)->fs.fsCsb[0] |= 1; (*insertface)->fs.fsCsb[0] |= 1;
else else
(*insertface)->fs.fsCsb[0] |= 1L << 31; (*insertface)->fs.fsCsb[0] |= 1L << 31;
} }
}
#ifdef HAVE_FREETYPE_FTWINFNT_H
else if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header)) {
CHARSETINFO csi;
TRACE("pix_h %d charset %d dpi %dx%d pt %d\n", winfnt_header.pixel_height, winfnt_header.charset,
winfnt_header.vertical_resolution,winfnt_header.horizontal_resolution, winfnt_header.nominal_point_size);
if(TranslateCharsetInfo((DWORD*)(UINT)winfnt_header.charset, &csi, TCI_SRCCHARSET))
memcpy(&(*insertface)->fs, &csi.fs, sizeof(csi.fs));
(*insertface)->size.internal_leading = winfnt_header.internal_leading;
}
#endif
TRACE("fsCsb = %08lx %08lx/%08lx %08lx %08lx %08lx\n",
(*insertface)->fs.fsCsb[0], (*insertface)->fs.fsCsb[1],
(*insertface)->fs.fsUsb[0], (*insertface)->fs.fsUsb[1],
(*insertface)->fs.fsUsb[2], (*insertface)->fs.fsUsb[3]);
if((*insertface)->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */ if((*insertface)->fs.fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
for(i = 0; i < ft_face->num_charmaps; i++) { for(i = 0; i < ft_face->num_charmaps; i++) {
@ -449,10 +558,11 @@ static BOOL AddFontFileToList(const char *file, char *fake_family, BOOL external
if((*insertface)->fs.fsCsb[0] & ~(1L << 31)) if((*insertface)->fs.fsCsb[0] & ~(1L << 31))
have_installed_roman_font = TRUE; have_installed_roman_font = TRUE;
} while(!FT_IS_SCALABLE(ft_face) && ++bitmap_num < ft_face->num_fixed_sizes);
num_faces = ft_face->num_faces; num_faces = ft_face->num_faces;
pFT_Done_Face(ft_face); pFT_Done_Face(ft_face);
TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), TRACE("Added font %s %s\n", debugstr_w((*pfamily)->FamilyName),
debugstr_w(StyleW)); debugstr_w(StyleW));
} while(num_faces > ++face_index); } while(num_faces > ++face_index);
return TRUE; return TRUE;
@ -466,7 +576,10 @@ static void DumpFontList(void)
for(family = FontList; family; family = family->next) { for(family = FontList; family; family = family->next) {
TRACE("Family: %s\n", debugstr_w(family->FamilyName)); TRACE("Family: %s\n", debugstr_w(family->FamilyName));
for(face = family->FirstFace; face; face = face->next) { for(face = family->FirstFace; face; face = face->next) {
TRACE("\t%s\n", debugstr_w(face->StyleName)); TRACE("\t%s", debugstr_w(face->StyleName));
if(!face->scalable)
TRACE(" %ld", face->size.y_ppem >> 6);
TRACE("\n");
} }
} }
return; return;
@ -624,7 +737,7 @@ static void LoadReplaceList(void)
TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName), TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
debugstr_w(face->StyleName), value); debugstr_w(face->StyleName), value);
/* Now add a new entry with the new family name */ /* Now add a new entry with the new family name */
AddFontFileToList(face->file, value, face->external); AddFontFileToList(face->file, value, face->external ? ADDFONT_EXTERNAL_FONT : 0);
} }
break; break;
} }
@ -671,7 +784,7 @@ static BOOL ReadFontDir(const char *dirname, BOOL external_fonts)
if(S_ISDIR(statbuf.st_mode)) if(S_ISDIR(statbuf.st_mode))
ReadFontDir(path, external_fonts); ReadFontDir(path, external_fonts);
else else
AddFontFileToList(path, NULL, external_fonts); AddFontFileToList(path, NULL, external_fonts ? ADDFONT_EXTERNAL_FONT : 0);
} }
closedir(dir); closedir(dir);
return TRUE; return TRUE;
@ -729,7 +842,7 @@ LOAD_FUNCPTR(FcPatternGet);
if(len < 4) continue; if(len < 4) continue;
ext = v.u.s + len - 3; ext = v.u.s + len - 3;
if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf")) if(!strcasecmp(ext, "ttf") || !strcasecmp(ext, "ttc") || !strcasecmp(ext, "otf"))
AddFontFileToList(v.u.s, NULL, TRUE); AddFontFileToList(v.u.s, NULL, ADDFONT_EXTERNAL_FONT);
} }
pFcFontSetDestroy(fontset); pFcFontSetDestroy(fontset);
pFcObjectSetDestroy(os); pFcObjectSetDestroy(os);
@ -739,6 +852,34 @@ LOAD_FUNCPTR(FcPatternGet);
return; return;
} }
void load_system_fonts(void)
{
HKEY hkey;
WCHAR data[MAX_PATH], windowsdir[MAX_PATH], pathW[MAX_PATH];
const WCHAR **value;
DWORD dlen, type;
static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
char *unixname;
if(RegOpenKeyW(HKEY_CURRENT_CONFIG, system_fonts_reg_key, &hkey) == ERROR_SUCCESS) {
GetWindowsDirectoryW(windowsdir, sizeof(windowsdir) / sizeof(WCHAR));
strcatW(windowsdir, fontsW);
for(value = SystemFontValues; *value; value++) {
dlen = sizeof(data);
if(RegQueryValueExW(hkey, *value, 0, &type, (void*)data, &dlen) == ERROR_SUCCESS &&
type == REG_SZ) {
sprintfW(pathW, fmtW, windowsdir, data);
if((unixname = wine_get_unix_file_name(pathW))) {
AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
HeapFree(GetProcessHeap(), 0, unixname);
}
}
}
RegCloseKey(hkey);
}
}
/************************************************************* /*************************************************************
* *
* This adds registry entries for any externally loaded fonts * This adds registry entries for any externally loaded fonts
@ -858,7 +999,7 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
if((unixname = wine_get_unix_file_name(file))) if((unixname = wine_get_unix_file_name(file)))
{ {
AddFontFileToList(unixname, NULL, FALSE); AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
HeapFree(GetProcessHeap(), 0, unixname); HeapFree(GetProcessHeap(), 0, unixname);
} }
} }
@ -882,7 +1023,7 @@ BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
*/ */
BOOL WineEngInit(void) BOOL WineEngInit(void)
{ {
static const WCHAR fontsW[] = {'\\','F','o','n','t','s','\0'}; static const WCHAR dot_fonW[] = {'.','f','o','n','\0'};
HKEY hkey; HKEY hkey;
DWORD valuelen, datalen, i = 0, type, dlen, vlen; DWORD valuelen, datalen, i = 0, type, dlen, vlen;
LPVOID data; LPVOID data;
@ -925,7 +1066,9 @@ BOOL WineEngInit(void)
pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0); pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0); pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0); pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
#ifdef HAVE_FREETYPE_FTWINFNT_H
pFT_Get_WinFNT_Header = wine_dlsym(ft_handle, "FT_Get_WinFNT_Header", NULL, 0);
#endif
if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) && if(!wine_dlsym(ft_handle, "FT_Get_Postscript_Name", NULL, 0) &&
!wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) { !wine_dlsym(ft_handle, "FT_Sqrt64", NULL, 0)) {
/* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and /* try to avoid 2.0.4: >= 2.0.5 has FT_Get_Postscript_Name and
@ -951,6 +1094,9 @@ BOOL WineEngInit(void)
FT_Version.patch=5; FT_Version.patch=5;
} }
TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch); TRACE("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
((FT_Version.minor << 8) & 0x00ff00) |
((FT_Version.patch ) & 0x0000ff);
if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) { if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) {
ERR("Failed to create font mutex\n"); ERR("Failed to create font mutex\n");
@ -967,9 +1113,13 @@ BOOL WineEngInit(void)
HeapFree(GetProcessHeap(), 0, unixname); HeapFree(GetProcessHeap(), 0, unixname);
} }
/* now load the system fonts */
load_system_fonts();
/* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts /* now look under HKLM\Software\Microsoft\Windows[ NT]\CurrentVersion\Fonts
for any fonts not installed in %WINDOWSDIR%\Fonts. They will have their for any fonts not installed in %WINDOWSDIR%\Fonts. They will have their
full path as the entry */ full path as the entry. Also look for any .fon fonts, since ReadFontDir
will skip these. */
if(RegOpenKeyW(HKEY_LOCAL_MACHINE, if(RegOpenKeyW(HKEY_LOCAL_MACHINE,
is_win9x() ? win9x_font_reg_key : winnt_font_reg_key, is_win9x() ? win9x_font_reg_key : winnt_font_reg_key,
&hkey) == ERROR_SUCCESS) { &hkey) == ERROR_SUCCESS) {
@ -987,11 +1137,24 @@ BOOL WineEngInit(void)
while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data, while(RegEnumValueW(hkey, i++, valueW, &vlen, NULL, &type, data,
&dlen) == ERROR_SUCCESS) { &dlen) == ERROR_SUCCESS) {
if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':') if(((LPWSTR)data)[0] && ((LPWSTR)data)[1] == ':')
{
if((unixname = wine_get_unix_file_name((LPWSTR)data))) if((unixname = wine_get_unix_file_name((LPWSTR)data)))
{ {
AddFontFileToList(unixname, NULL, FALSE); AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
HeapFree(GetProcessHeap(), 0, unixname); HeapFree(GetProcessHeap(), 0, unixname);
} }
}
else if(dlen / 2 >= 6 && !strcmpiW(((LPWSTR)data) + dlen / 2 - 5, dot_fonW))
{
WCHAR pathW[MAX_PATH];
static const WCHAR fmtW[] = {'%','s','\\','%','s','\0'};
sprintfW(pathW, fmtW, windowsdir, data);
if((unixname = wine_get_unix_file_name(pathW)))
{
AddFontFileToList(unixname, NULL, ADDFONT_FORCE_BITMAP);
HeapFree(GetProcessHeap(), 0, unixname);
}
}
/* reset dlen and vlen */ /* reset dlen and vlen */
dlen = datalen; dlen = datalen;
vlen = valuelen; vlen = valuelen;
@ -1094,7 +1257,7 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height)
static LONG load_VDMX(GdiFont, LONG); static LONG load_VDMX(GdiFont, LONG);
static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG height) static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG width, LONG height)
{ {
FT_Error err; FT_Error err;
FT_Face ft_face; FT_Face ft_face;
@ -1109,13 +1272,18 @@ static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG h
/* set it here, as load_VDMX needs it */ /* set it here, as load_VDMX needs it */
font->ft_face = ft_face; font->ft_face = ft_face;
if(FT_IS_SCALABLE(ft_face)) {
/* load the VDMX table if we have one */ /* load the VDMX table if we have one */
ppem = load_VDMX(font, height); ppem = load_VDMX(font, height);
if(ppem == 0) if(ppem == 0)
ppem = calc_ppem_for_height(ft_face, height); ppem = calc_ppem_for_height(ft_face, height);
pFT_Set_Pixel_Sizes(ft_face, 0, ppem); if((err = pFT_Set_Pixel_Sizes(ft_face, 0, ppem)) != 0)
WARN("FT_Set_Pixel_Sizes %d, %ld rets %x\n", 0, ppem, err);
} else {
if((err = pFT_Set_Pixel_Sizes(ft_face, width, height)) != 0)
WARN("FT_Set_Pixel_Sizes %ld, %ld rets %x\n", width, height, err);
}
return ft_face; return ft_face;
} }
@ -1327,14 +1495,16 @@ static LONG load_VDMX(GdiFont font, LONG height)
GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
{ {
GdiFont ret; GdiFont ret;
Face *face; Face *face, *best;
Family *family = NULL; Family *family = NULL;
INT height; INT height, width = 0;
BOOL bd, it; signed int diff = 0, newdiff;
BOOL bd, it, can_use_bitmap;
LOGFONTW lf; LOGFONTW lf;
CHARSETINFO csi; CHARSETINFO csi;
if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL; if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE;
TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n", TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n",
debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic, debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic,
@ -1343,7 +1513,9 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
/* check the cache first */ /* check the cache first */
for(ret = GdiFontList; ret; ret = ret->next) { for(ret = GdiFontList; ret; ret = ret->next) {
if(ret->hfont == hfont && !memcmp(&ret->xform, &dc->xformWorld2Vport, offsetof(XFORM, eDx))) { if(ret->hfont == hfont && !memcmp(&ret->xform, &dc->xformWorld2Vport, offsetof(XFORM, eDx)) &&
(can_use_bitmap || FT_IS_SCALABLE(ret->ft_face))) {
TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont); TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont);
return ret; return ret;
} }
@ -1400,28 +1572,11 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
for(family = FontList; family; family = family->next) { for(family = FontList; family; family = family->next) {
if(!strcmpiW(family->FamilyName, lf.lfFaceName)) if(!strcmpiW(family->FamilyName, lf.lfFaceName))
if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0]) if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
break; if(family->FirstFace->scalable || can_use_bitmap)
}
if(!family) { /* do other aliases here */
if(!strcmpiW(lf.lfFaceName, SystemW))
strcpyW(lf.lfFaceName, defSystem);
else if(!strcmpiW(lf.lfFaceName, MSSansSerifW))
strcpyW(lf.lfFaceName, defSans);
else if(!strcmpiW(lf.lfFaceName, HelvW))
strcpyW(lf.lfFaceName, defSans);
else
goto not_found;
for(family = FontList; family; family = family->next) {
if(!strcmpiW(family->FamilyName, lf.lfFaceName))
if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
break; break;
} }
} }
}
not_found:
if(!family) { if(!family) {
/* If requested charset was DEFAULT_CHARSET then try using charset /* If requested charset was DEFAULT_CHARSET then try using charset
corresponding to the current ansi codepage */ corresponding to the current ansi codepage */
@ -1449,6 +1604,7 @@ not_found:
for(family = FontList; family; family = family->next) { for(family = FontList; family; family = family->next) {
if(!strcmpiW(family->FamilyName, lf.lfFaceName) && if(!strcmpiW(family->FamilyName, lf.lfFaceName) &&
(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0])) (csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]))
if(family->FirstFace->scalable || can_use_bitmap)
break; break;
} }
} }
@ -1456,6 +1612,7 @@ not_found:
if(!family) { if(!family) {
for(family = FontList; family; family = family->next) { for(family = FontList; family; family = family->next) {
if(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) if(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0])
if(family->FirstFace->scalable || can_use_bitmap)
break; break;
} }
} }
@ -1469,11 +1626,31 @@ not_found:
it = lf.lfItalic ? 1 : 0; it = lf.lfItalic ? 1 : 0;
bd = lf.lfWeight > 550 ? 1 : 0; bd = lf.lfWeight > 550 ? 1 : 0;
height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
height = lf.lfHeight < 0 ? -abs(height) : abs(height);
best = NULL;
for(face = family->FirstFace; face; face = face->next) { for(face = family->FirstFace; face; face = face->next) {
if(!(face->Italic ^ it) && !(face->Bold ^ bd)) if(!(face->Italic ^ it) && !(face->Bold ^ bd)) {
if(face->scalable)
break;
if(height > 0)
newdiff = height - (signed int)(face->size.y_ppem >> 6);
else
newdiff = -height - ((signed int)(face->size.y_ppem >> 6) - face->size.internal_leading);
if(!best || (diff > 0 && newdiff < diff && newdiff >= 0) ||
(diff < 0 && newdiff > diff)) {
TRACE("%ld is better for %d diff was %d\n", face->size.y_ppem >> 6, height, diff);
diff = newdiff;
best = face;
if(diff == 0)
break; break;
} }
if(!face) { }
}
if(!face && best)
face = best;
else if(!face) {
face = family->FirstFace; face = family->FirstFace;
if(it && !face->Italic) ret->fake_italic = TRUE; if(it && !face->Italic) ret->fake_italic = TRUE;
if(bd && !face->Bold) ret->fake_bold = TRUE; if(bd && !face->Bold) ret->fake_bold = TRUE;
@ -1489,9 +1666,12 @@ not_found:
TRACE("Chosen: %s %s\n", debugstr_w(family->FamilyName), TRACE("Chosen: %s %s\n", debugstr_w(family->FamilyName),
debugstr_w(face->StyleName)); debugstr_w(face->StyleName));
height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 ); if(!face->scalable) {
ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width = face->size.x_ppem >> 6;
lf.lfHeight < 0 ? -abs(height) : abs(height)); height = face->size.y_ppem >> 6;
}
ret->ft_face = OpenFontFile(ret, face->file, face->face_index, width, height);
if (!ret->ft_face) if (!ret->ft_face)
{ {
free_font( ret ); free_font( ret );
@ -1574,11 +1754,21 @@ BOOL WineEngDestroyFontInstance(HFONT handle)
static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
NEWTEXTMETRICEXW *pntm, LPDWORD ptype) NEWTEXTMETRICEXW *pntm, LPDWORD ptype)
{ {
OUTLINETEXTMETRICW *potm; OUTLINETEXTMETRICW *potm = NULL;
UINT size; UINT size;
TEXTMETRICW tm, *ptm;
GdiFont font = alloc_font(); GdiFont font = alloc_font();
LONG width, height;
if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, 100))) if(face->scalable) {
height = 100;
width = 0;
} else {
height = face->size.y_ppem >> 6;
width = face->size.x_ppem >> 6;
}
if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, width, height)))
{ {
free_font(font); free_font(font);
return; return;
@ -1589,49 +1779,53 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW)); memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
size = WineEngGetOutlineTextMetrics(font, 0, NULL); size = WineEngGetOutlineTextMetrics(font, 0, NULL);
if(size) {
potm = HeapAlloc(GetProcessHeap(), 0, size); potm = HeapAlloc(GetProcessHeap(), 0, size);
WineEngGetOutlineTextMetrics(font, size, potm); WineEngGetOutlineTextMetrics(font, size, potm);
ptm = (TEXTMETRICW*)&potm->otmTextMetrics;
} else {
WineEngGetTextMetrics(font, &tm);
ptm = &tm;
}
#define TM potm->otmTextMetrics pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = ptm->tmHeight;
pntm->ntmTm.tmAscent = ptm->tmAscent;
pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = TM.tmHeight; pntm->ntmTm.tmDescent = ptm->tmDescent;
pntm->ntmTm.tmAscent = TM.tmAscent; pntm->ntmTm.tmInternalLeading = ptm->tmInternalLeading;
pntm->ntmTm.tmDescent = TM.tmDescent; pntm->ntmTm.tmExternalLeading = ptm->tmExternalLeading;
pntm->ntmTm.tmInternalLeading = TM.tmInternalLeading; pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = ptm->tmAveCharWidth;
pntm->ntmTm.tmExternalLeading = TM.tmExternalLeading; pntm->ntmTm.tmMaxCharWidth = ptm->tmMaxCharWidth;
pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = TM.tmAveCharWidth; pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = ptm->tmWeight;
pntm->ntmTm.tmMaxCharWidth = TM.tmMaxCharWidth; pntm->ntmTm.tmOverhang = ptm->tmOverhang;
pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = TM.tmWeight; pntm->ntmTm.tmDigitizedAspectX = ptm->tmDigitizedAspectX;
pntm->ntmTm.tmOverhang = TM.tmOverhang; pntm->ntmTm.tmDigitizedAspectY = ptm->tmDigitizedAspectY;
pntm->ntmTm.tmDigitizedAspectX = TM.tmDigitizedAspectX; pntm->ntmTm.tmFirstChar = ptm->tmFirstChar;
pntm->ntmTm.tmDigitizedAspectY = TM.tmDigitizedAspectY; pntm->ntmTm.tmLastChar = ptm->tmLastChar;
pntm->ntmTm.tmFirstChar = TM.tmFirstChar; pntm->ntmTm.tmDefaultChar = ptm->tmDefaultChar;
pntm->ntmTm.tmLastChar = TM.tmLastChar; pntm->ntmTm.tmBreakChar = ptm->tmBreakChar;
pntm->ntmTm.tmDefaultChar = TM.tmDefaultChar; pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = ptm->tmItalic;
pntm->ntmTm.tmBreakChar = TM.tmBreakChar; pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = ptm->tmUnderlined;
pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = TM.tmItalic; pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = ptm->tmStruckOut;
pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = TM.tmUnderlined; pntm->ntmTm.tmPitchAndFamily = ptm->tmPitchAndFamily;
pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = TM.tmStruckOut; pelf->elfLogFont.lfPitchAndFamily = (ptm->tmPitchAndFamily & 0xf1) + 1;
pntm->ntmTm.tmPitchAndFamily = TM.tmPitchAndFamily; pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = ptm->tmCharSet;
pelf->elfLogFont.lfPitchAndFamily = (TM.tmPitchAndFamily & 0xf1) + 1;
pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = TM.tmCharSet;
pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS; pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS;
pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS; pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
pelf->elfLogFont.lfQuality = DRAFT_QUALITY; pelf->elfLogFont.lfQuality = DRAFT_QUALITY;
pntm->ntmTm.ntmFlags = TM.tmItalic ? NTM_ITALIC : 0; *ptype = ptm->tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
if(TM.tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD; if(!(ptm->tmPitchAndFamily & TMPF_VECTOR))
*ptype |= RASTER_FONTTYPE;
if(potm) {
pntm->ntmTm.ntmFlags = ptm->tmItalic ? NTM_ITALIC : 0;
if(ptm->tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD;
if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR; if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR;
pntm->ntmTm.ntmSizeEM = potm->otmEMSquare; pntm->ntmTm.ntmSizeEM = potm->otmEMSquare;
pntm->ntmTm.ntmCellHeight = 0; pntm->ntmTm.ntmCellHeight = 0;
pntm->ntmTm.ntmAvgWidth = 0; pntm->ntmTm.ntmAvgWidth = 0;
*ptype = TM.tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0;
if(!(TM.tmPitchAndFamily & TMPF_VECTOR))
*ptype |= RASTER_FONTTYPE;
#undef TM
memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE)); memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE));
strncpyW(pelf->elfLogFont.lfFaceName, strncpyW(pelf->elfLogFont.lfFaceName,
@ -1643,6 +1837,13 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
strncpyW(pelf->elfStyle, strncpyW(pelf->elfStyle,
(WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName), (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName),
LF_FACESIZE); LF_FACESIZE);
} else {
strncpyW(pelf->elfLogFont.lfFaceName, face->family->FamilyName, LF_FACESIZE);
strncpyW(pelf->elfFullName, face->family->FamilyName, LF_FACESIZE);
pelf->elfStyle[0] = '\0';
}
pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */ pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */
HeapFree(GetProcessHeap(), 0, potm); HeapFree(GetProcessHeap(), 0, potm);
@ -1687,7 +1888,13 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
for(face = family->FirstFace; face; face = face->next) { for(face = family->FirstFace; face; face = face->next) {
GetEnumStructs(face, &elf, &ntm, &type); GetEnumStructs(face, &elf, &ntm, &type);
for(i = 0; i < 32; i++) { for(i = 0; i < 32; i++) {
if(face->fs.fsCsb[0] & (1L << i)) { if(!face->scalable && face->fs.fsCsb[0] == 0) { /* OEM bitmap */
elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
strcpyW(elf.elfScript, OEM_DOSW);
i = 32; /* break out of loop */
} else if(!(face->fs.fsCsb[0] & (1L << i)))
continue;
else {
fs.fsCsb[0] = 1L << i; fs.fsCsb[0] = 1L << i;
fs.fsCsb[1] = 0; fs.fsCsb[1] = 0;
if(!TranslateCharsetInfo(fs.fsCsb, &csi, if(!TranslateCharsetInfo(fs.fsCsb, &csi,
@ -1701,6 +1908,8 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
strcpyW(elf.elfScript, ElfScriptsW[i]); strcpyW(elf.elfScript, ElfScriptsW[i]);
else else
FIXME("Unknown elfscript for bit %d\n", i); FIXME("Unknown elfscript for bit %d\n", i);
}
}
TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n", TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
debugstr_w(elf.elfLogFont.lfFaceName), debugstr_w(elf.elfLogFont.lfFaceName),
debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle), debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
@ -1713,13 +1922,17 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
} }
} }
} }
}
}
} else { } else {
for(family = FontList; family; family = family->next) { for(family = FontList; family; family = family->next) {
GetEnumStructs(family->FirstFace, &elf, &ntm, &type); GetEnumStructs(family->FirstFace, &elf, &ntm, &type);
for(i = 0; i < 32; i++) { for(i = 0; i < 32; i++) {
if(family->FirstFace->fs.fsCsb[0] & (1L << i)) { if(!family->FirstFace->scalable && family->FirstFace->fs.fsCsb[0] == 0) { /* OEM bitmap */
elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = OEM_CHARSET;
strcpyW(elf.elfScript, OEM_DOSW);
i = 32; /* break out of loop */
} else if(!(family->FirstFace->fs.fsCsb[0] & (1L << i)))
continue;
else {
fs.fsCsb[0] = 1L << i; fs.fsCsb[0] = 1L << i;
fs.fsCsb[1] = 0; fs.fsCsb[1] = 0;
if(!TranslateCharsetInfo(fs.fsCsb, &csi, if(!TranslateCharsetInfo(fs.fsCsb, &csi,
@ -1733,6 +1946,8 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
strcpyW(elf.elfScript, ElfScriptsW[i]); strcpyW(elf.elfScript, ElfScriptsW[i]);
else else
FIXME("Unknown elfscript for bit %d\n", i); FIXME("Unknown elfscript for bit %d\n", i);
}
}
TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n", TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n",
debugstr_w(elf.elfLogFont.lfFaceName), debugstr_w(elf.elfLogFont.lfFaceName),
debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle), debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle),
@ -1744,8 +1959,6 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
} }
} }
} }
}
}
end: end:
return ret; return ret;
} }
@ -1946,7 +2159,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
} }
if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) { if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
FIXME("loaded a bitmap\n"); TRACE("loaded a bitmap\n");
return GDI_ERROR; return GDI_ERROR;
} }
@ -2236,6 +2449,71 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
return needed; return needed;
} }
static BOOL get_bitmap_text_metrics(GdiFont font)
{
FT_Face ft_face = font->ft_face;
#ifdef HAVE_FREETYPE_FTWINFNT_H
FT_WinFNT_HeaderRec winfnt_header;
#endif
const DWORD size = offsetof(OUTLINETEXTMETRICW, otmFiller);
font->potm = HeapAlloc(GetProcessHeap(), 0, size);
font->potm->otmSize = size;
#define TM font->potm->otmTextMetrics
#ifdef HAVE_FREETYPE_FTWINFNT_H
if(pFT_Get_WinFNT_Header && !pFT_Get_WinFNT_Header(ft_face, &winfnt_header))
{
TM.tmHeight = winfnt_header.pixel_height;
TM.tmAscent = winfnt_header.ascent;
TM.tmDescent = TM.tmHeight - TM.tmAscent;
TM.tmInternalLeading = winfnt_header.internal_leading;
TM.tmExternalLeading = winfnt_header.external_leading;
TM.tmAveCharWidth = winfnt_header.avg_width;
TM.tmMaxCharWidth = winfnt_header.max_width;
TM.tmWeight = winfnt_header.weight;
TM.tmOverhang = 0;
TM.tmDigitizedAspectX = winfnt_header.horizontal_resolution;
TM.tmDigitizedAspectY = winfnt_header.vertical_resolution;
TM.tmFirstChar = winfnt_header.first_char;
TM.tmLastChar = winfnt_header.last_char;
TM.tmDefaultChar = winfnt_header.default_char;
TM.tmBreakChar = winfnt_header.break_char;
TM.tmItalic = winfnt_header.italic;
TM.tmUnderlined = winfnt_header.underline;
TM.tmStruckOut = winfnt_header.strike_out;
TM.tmPitchAndFamily = winfnt_header.pitch_and_family;
TM.tmCharSet = winfnt_header.charset;
}
else
#endif
{
TM.tmAscent = ft_face->size->metrics.ascender >> 6;
TM.tmDescent = -ft_face->size->metrics.descender >> 6;
TM.tmHeight = TM.tmAscent + TM.tmDescent;
TM.tmInternalLeading = TM.tmHeight - ft_face->size->metrics.y_ppem;
TM.tmExternalLeading = (ft_face->size->metrics.height >> 6) - TM.tmHeight;
TM.tmMaxCharWidth = ft_face->size->metrics.max_advance >> 6;
TM.tmAveCharWidth = TM.tmMaxCharWidth * 2 / 3; /* FIXME */
TM.tmWeight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? FW_BOLD : FW_NORMAL;
TM.tmOverhang = 0;
TM.tmDigitizedAspectX = 96; /* FIXME */
TM.tmDigitizedAspectY = 96; /* FIXME */
TM.tmFirstChar = 1;
TM.tmLastChar = 255;
TM.tmDefaultChar = 32;
TM.tmBreakChar = 32;
TM.tmItalic = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
TM.tmUnderlined = 0;
TM.tmStruckOut = 0;
/* NB inverted meaning of TMPF_FIXED_PITCH */
TM.tmPitchAndFamily = ft_face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ? 0 : TMPF_FIXED_PITCH;
TM.tmCharSet = font->charset;
}
#undef TM
return TRUE;
}
/************************************************************* /*************************************************************
* WineEngGetTextMetrics * WineEngGetTextMetrics
* *
@ -2244,6 +2522,7 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
{ {
if(!font->potm) { if(!font->potm) {
if(!WineEngGetOutlineTextMetrics(font, 0, NULL)) if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
if(!get_bitmap_text_metrics(font))
return FALSE; return FALSE;
} }
if(!font->potm) return FALSE; if(!font->potm) return FALSE;
@ -2276,12 +2555,16 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
TRACE("font=%p\n", font); TRACE("font=%p\n", font);
if(!FT_IS_SCALABLE(ft_face))
return 0;
if(font->potm) { if(font->potm) {
if(cbSize >= font->potm->otmSize) if(cbSize >= font->potm->otmSize)
memcpy(potm, font->potm, font->potm->otmSize); memcpy(potm, font->potm, font->potm->otmSize);
return font->potm->otmSize; return font->potm->otmSize;
} }
needed = sizeof(*potm); needed = sizeof(*potm);
lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR); lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);

View File

@ -110,6 +110,9 @@
/* Define if you have the <freetype/fttrigon.h> header file. */ /* Define if you have the <freetype/fttrigon.h> header file. */
#undef HAVE_FREETYPE_FTTRIGON_H #undef HAVE_FREETYPE_FTTRIGON_H
/* Define to 1 if you have the <freetype/ftwinfnt.h> header file. */
#undef HAVE_FREETYPE_FTWINFNT_H
/* Define to 1 if you have the <freetype/internal/sfnt.h> header file. */ /* Define to 1 if you have the <freetype/internal/sfnt.h> header file. */
#undef HAVE_FREETYPE_INTERNAL_SFNT_H #undef HAVE_FREETYPE_INTERNAL_SFNT_H

View File

@ -627,8 +627,9 @@ static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *p
DC *dc; DC *dc;
/* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */ /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
pfe->lpLogFontParam->lfCharSet == plf->lfCharSet ) pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
(!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
{ {
/* convert font metrics */ /* convert font metrics */
ENUMLOGFONTEXA logfont; ENUMLOGFONTEXA logfont;