forked from Mirrors/wine-wine
Don't enable client side fonts unless we have at least one non-symbol
font installed - this avoids a nasty Wingdings only scenario. Add the ability to perform font replacements, this essentially lets you give a second name to a font family so that familyA gets enumerated as familyB too. If we encounter two copies of the same font then use the one with the larger version number. Dmitry Timoshkov <dmitry@codeweavers.com> Move GetTextCharsetInfo implementation to the font driver.oldstable
parent
6fcf40197c
commit
c23f8578c3
|
@ -105,6 +105,7 @@ MAKE_FUNCPTR(FT_Sin);
|
||||||
MAKE_FUNCPTR(FT_Vector_Rotate);
|
MAKE_FUNCPTR(FT_Vector_Rotate);
|
||||||
#undef MAKE_FUNCPTR
|
#undef MAKE_FUNCPTR
|
||||||
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*);
|
||||||
|
|
||||||
#define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
|
#define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
|
||||||
|
|
||||||
|
@ -114,8 +115,10 @@ typedef struct tagFace {
|
||||||
FT_Long face_index;
|
FT_Long face_index;
|
||||||
BOOL Italic;
|
BOOL Italic;
|
||||||
BOOL Bold;
|
BOOL Bold;
|
||||||
DWORD fsCsb[2]; /* codepage bitfield from FONTSIGNATURE */
|
FONTSIGNATURE fs;
|
||||||
|
FT_Fixed font_version;
|
||||||
struct tagFace *next;
|
struct tagFace *next;
|
||||||
|
struct tagFamily *family;
|
||||||
} Face;
|
} Face;
|
||||||
|
|
||||||
typedef struct tagFamily {
|
typedef struct tagFamily {
|
||||||
|
@ -146,6 +149,7 @@ struct tagGdiFont {
|
||||||
SHORT yMax;
|
SHORT yMax;
|
||||||
SHORT yMin;
|
SHORT yMin;
|
||||||
OUTLINETEXTMETRICW *potm;
|
OUTLINETEXTMETRICW *potm;
|
||||||
|
FONTSIGNATURE fs;
|
||||||
struct tagGdiFont *next;
|
struct tagGdiFont *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,21 +222,25 @@ typedef struct tagFontSubst {
|
||||||
} FontSubst;
|
} FontSubst;
|
||||||
|
|
||||||
static FontSubst *substlist = NULL;
|
static FontSubst *substlist = NULL;
|
||||||
|
static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */
|
||||||
|
|
||||||
static BOOL AddFontFileToList(char *file)
|
static BOOL AddFontFileToList(char *file, char *fake_family)
|
||||||
{
|
{
|
||||||
FT_Face ft_face;
|
FT_Face ft_face;
|
||||||
TT_OS2 *pOS2;
|
TT_OS2 *pOS2;
|
||||||
|
TT_Header *pHeader;
|
||||||
WCHAR *FamilyW, *StyleW;
|
WCHAR *FamilyW, *StyleW;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
Family *family = FontList;
|
Family *family = FontList;
|
||||||
Family **insert = &FontList;
|
Family **insert = &FontList;
|
||||||
Face **insertface;
|
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;
|
int i;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
char *family_name = fake_family;
|
||||||
|
|
||||||
TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
|
TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
|
||||||
if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
|
if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
|
||||||
WARN("Unable to load font file %s err = %x\n", debugstr_a(file), err);
|
WARN("Unable to load font file %s err = %x\n", debugstr_a(file), err);
|
||||||
|
@ -244,16 +252,26 @@ static BOOL AddFontFileToList(char *file)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if(!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
|
if(!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) ||
|
||||||
TRACE("Font file %s lacks either an OS2 or HHEA table.\n"
|
!(pHeader = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_head))) {
|
||||||
|
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);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0);
|
if(!ft_face->family_name || !ft_face->style_name) {
|
||||||
|
TRACE("Font file %s lacks either a family or style name\n", debugstr_a(file));
|
||||||
|
pFT_Done_Face(ft_face);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!family_name)
|
||||||
|
family_name = ft_face->family_name;
|
||||||
|
|
||||||
|
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, ft_face->family_name, -1, FamilyW, len);
|
MultiByteToWideChar(CP_ACP, 0, family_name, -1, FamilyW, len);
|
||||||
|
|
||||||
while(family) {
|
while(family) {
|
||||||
if(!strcmpW(family->FamilyName, FamilyW))
|
if(!strcmpW(family->FamilyName, FamilyW))
|
||||||
|
@ -274,49 +292,85 @@ static BOOL AddFontFileToList(char *file)
|
||||||
StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
|
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
|
||||||
|
|
||||||
|
next = NULL;
|
||||||
for(insertface = &family->FirstFace; *insertface;
|
for(insertface = &family->FirstFace; *insertface;
|
||||||
insertface = &(*insertface)->next) {
|
insertface = &(*insertface)->next) {
|
||||||
if(!strcmpW((*insertface)->StyleName, StyleW)) {
|
if(!strcmpW((*insertface)->StyleName, StyleW)) {
|
||||||
TRACE("Already loaded font %s %s\n", debugstr_w(family->FamilyName),
|
TRACE("Already loaded font %s %s original version is %lx, this version is %lx\n",
|
||||||
debugstr_w(StyleW));
|
debugstr_w(family->FamilyName), debugstr_w(StyleW),
|
||||||
|
(*insertface)->font_version, pHeader->Font_Revision);
|
||||||
|
|
||||||
|
if(fake_family) {
|
||||||
|
TRACE("This font is a replacement but the original really exists, so we'll skip the replacement\n");
|
||||||
HeapFree(GetProcessHeap(), 0, StyleW);
|
HeapFree(GetProcessHeap(), 0, StyleW);
|
||||||
pFT_Done_Face(ft_face);
|
pFT_Done_Face(ft_face);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if(pHeader->Font_Revision <= (*insertface)->font_version) {
|
||||||
|
TRACE("Original font is newer so skipping this one\n");
|
||||||
|
HeapFree(GetProcessHeap(), 0, StyleW);
|
||||||
|
pFT_Done_Face(ft_face);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
TRACE("Replacing original with this one\n");
|
||||||
|
next = (*insertface)->next;
|
||||||
|
HeapFree(GetProcessHeap(), 0, (*insertface)->file);
|
||||||
|
HeapFree(GetProcessHeap(), 0, (*insertface)->StyleName);
|
||||||
|
HeapFree(GetProcessHeap(), 0, *insertface);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
|
*insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
|
||||||
(*insertface)->StyleName = StyleW;
|
(*insertface)->StyleName = StyleW;
|
||||||
(*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
|
(*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
|
||||||
strcpy((*insertface)->file, file);
|
strcpy((*insertface)->file, file);
|
||||||
(*insertface)->face_index = face_index;
|
(*insertface)->face_index = face_index;
|
||||||
(*insertface)->next = NULL;
|
(*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)->family = family;
|
||||||
|
|
||||||
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
|
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
|
||||||
if(pOS2) {
|
if(pOS2) {
|
||||||
(*insertface)->fsCsb[0] = pOS2->ulCodePageRange1;
|
(*insertface)->fs.fsCsb[0] = pOS2->ulCodePageRange1;
|
||||||
(*insertface)->fsCsb[1] = pOS2->ulCodePageRange2;
|
(*insertface)->fs.fsCsb[1] = pOS2->ulCodePageRange2;
|
||||||
|
(*insertface)->fs.fsUsb[0] = pOS2->ulUnicodeRange1;
|
||||||
|
(*insertface)->fs.fsUsb[1] = pOS2->ulUnicodeRange2;
|
||||||
|
(*insertface)->fs.fsUsb[2] = pOS2->ulUnicodeRange3;
|
||||||
|
(*insertface)->fs.fsUsb[3] = pOS2->ulUnicodeRange4;
|
||||||
} else {
|
} else {
|
||||||
(*insertface)->fsCsb[0] = (*insertface)->fsCsb[1] = 0;
|
(*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\n", (*insertface)->fsCsb[0], (*insertface)->fsCsb[1]);
|
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)->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 &&
|
for(i = 0; i < ft_face->num_charmaps &&
|
||||||
!(*insertface)->fsCsb[0]; i++) {
|
!(*insertface)->fs.fsCsb[0]; i++) {
|
||||||
switch(ft_face->charmaps[i]->encoding) {
|
switch(ft_face->charmaps[i]->encoding) {
|
||||||
case ft_encoding_unicode:
|
case ft_encoding_unicode:
|
||||||
(*insertface)->fsCsb[0] = 1;
|
(*insertface)->fs.fsCsb[0] = 1;
|
||||||
break;
|
break;
|
||||||
case ft_encoding_symbol:
|
case ft_encoding_symbol:
|
||||||
(*insertface)->fsCsb[0] = 1L << 31;
|
(*insertface)->fs.fsCsb[0] = 1L << 31;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((*insertface)->fs.fsCsb[0] & ~(1L << 31))
|
||||||
|
have_installed_roman_font = TRUE;
|
||||||
|
|
||||||
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(family->FamilyName),
|
||||||
|
@ -441,6 +495,72 @@ static void LoadSubstList(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************
|
||||||
|
* The replacement list is a way to map an entire font
|
||||||
|
* family onto another family. For example adding
|
||||||
|
*
|
||||||
|
* [HKLM\Software\Wine\Wine\FontReplacements]
|
||||||
|
* "Wingdings"="Winedings"
|
||||||
|
*
|
||||||
|
* would enumerate the Winedings font both as Winedings and
|
||||||
|
* Wingdings. However if a real Wingdings font is present the
|
||||||
|
* replacement does not take place.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void LoadReplaceList(void)
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
DWORD valuelen, datalen, i = 0, type, dlen, vlen;
|
||||||
|
LPSTR value;
|
||||||
|
LPVOID data;
|
||||||
|
Family *family;
|
||||||
|
Face *face;
|
||||||
|
WCHAR old_nameW[200];
|
||||||
|
|
||||||
|
if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
|
||||||
|
"Software\\Wine\\Wine\\FontReplacements",
|
||||||
|
&hkey) == ERROR_SUCCESS) {
|
||||||
|
|
||||||
|
RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
&valuelen, &datalen, NULL, NULL);
|
||||||
|
|
||||||
|
valuelen++; /* returned value doesn't include room for '\0' */
|
||||||
|
value = HeapAlloc(GetProcessHeap(), 0, valuelen * sizeof(CHAR));
|
||||||
|
data = HeapAlloc(GetProcessHeap(), 0, datalen);
|
||||||
|
|
||||||
|
dlen = datalen;
|
||||||
|
vlen = valuelen;
|
||||||
|
while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
|
||||||
|
&dlen) == ERROR_SUCCESS) {
|
||||||
|
TRACE("Got %s=%s\n", debugstr_a(value), debugstr_a(data));
|
||||||
|
/* "NewName"="Oldname" */
|
||||||
|
if(!MultiByteToWideChar(CP_ACP, 0, data, -1, old_nameW, sizeof(old_nameW)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Find the old family and hence all of the font files
|
||||||
|
in that family */
|
||||||
|
for(family = FontList; family; family = family->next) {
|
||||||
|
if(!strcmpiW(family->FamilyName, old_nameW)) {
|
||||||
|
for(face = family->FirstFace; face; face = face->next) {
|
||||||
|
TRACE("mapping %s %s to %s\n", debugstr_w(family->FamilyName),
|
||||||
|
debugstr_w(face->StyleName), value);
|
||||||
|
/* Now add a new entry with the new family name */
|
||||||
|
AddFontFileToList(face->file, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* reset dlen and vlen */
|
||||||
|
dlen = datalen;
|
||||||
|
vlen = valuelen;
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, data);
|
||||||
|
HeapFree(GetProcessHeap(), 0, value);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL ReadFontDir(char *dirname)
|
static BOOL ReadFontDir(char *dirname)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
@ -472,7 +592,7 @@ static BOOL ReadFontDir(char *dirname)
|
||||||
if(S_ISDIR(statbuf.st_mode))
|
if(S_ISDIR(statbuf.st_mode))
|
||||||
ReadFontDir(path);
|
ReadFontDir(path);
|
||||||
else
|
else
|
||||||
AddFontFileToList(path);
|
AddFontFileToList(path, NULL);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -495,7 +615,7 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
|
||||||
FIXME("Ignoring flags %lx\n", flags);
|
FIXME("Ignoring flags %lx\n", flags);
|
||||||
|
|
||||||
if(wine_get_unix_file_name(fileA, unixname, sizeof(unixname)))
|
if(wine_get_unix_file_name(fileA, unixname, sizeof(unixname)))
|
||||||
AddFontFileToList(unixname);
|
AddFontFileToList(unixname, NULL);
|
||||||
HeapFree(GetProcessHeap(), 0, fileA);
|
HeapFree(GetProcessHeap(), 0, fileA);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -558,6 +678,7 @@ BOOL WineEngInit(void)
|
||||||
#undef LOAD_FUNCPTR
|
#undef LOAD_FUNCPTR
|
||||||
/* Don't warn if this one is missing */
|
/* Don't warn if this one is missing */
|
||||||
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);
|
||||||
|
|
||||||
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)) {
|
||||||
|
@ -610,7 +731,7 @@ BOOL WineEngInit(void)
|
||||||
&dlen) == ERROR_SUCCESS) {
|
&dlen) == ERROR_SUCCESS) {
|
||||||
if(((LPSTR)data)[0] && ((LPSTR)data)[1] == ':')
|
if(((LPSTR)data)[0] && ((LPSTR)data)[1] == ':')
|
||||||
if(wine_get_unix_file_name((LPSTR)data, unixname, sizeof(unixname)))
|
if(wine_get_unix_file_name((LPSTR)data, unixname, sizeof(unixname)))
|
||||||
AddFontFileToList(unixname);
|
AddFontFileToList(unixname, NULL);
|
||||||
|
|
||||||
/* reset dlen and vlen */
|
/* reset dlen and vlen */
|
||||||
dlen = datalen;
|
dlen = datalen;
|
||||||
|
@ -653,6 +774,7 @@ BOOL WineEngInit(void)
|
||||||
DumpFontList();
|
DumpFontList();
|
||||||
LoadSubstList();
|
LoadSubstList();
|
||||||
DumpSubstList();
|
DumpSubstList();
|
||||||
|
LoadReplaceList();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
sym_not_found:
|
sym_not_found:
|
||||||
WINE_MESSAGE(
|
WINE_MESSAGE(
|
||||||
|
@ -738,12 +860,12 @@ static int get_nearest_charset(Face *face)
|
||||||
DWORD fs0;
|
DWORD fs0;
|
||||||
|
|
||||||
if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
|
if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
|
||||||
if(csi.fs.fsCsb[0] & face->fsCsb[0])
|
if(csi.fs.fsCsb[0] & face->fs.fsCsb[0])
|
||||||
return csi.ciCharset;
|
return csi.ciCharset;
|
||||||
|
|
||||||
for(i = 0; i < 32; i++) {
|
for(i = 0; i < 32; i++) {
|
||||||
fs0 = 1L << i;
|
fs0 = 1L << i;
|
||||||
if(face->fsCsb[0] & fs0) {
|
if(face->fs.fsCsb[0] & fs0) {
|
||||||
if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
|
if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
|
||||||
return csi.ciCharset;
|
return csi.ciCharset;
|
||||||
else
|
else
|
||||||
|
@ -751,8 +873,8 @@ static int get_nearest_charset(Face *face)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FIXME("returning DEFAULT_CHARSET face->fsCsb[0] = %08lx file = %s\n",
|
FIXME("returning DEFAULT_CHARSET face->fs.fsCsb[0] = %08lx file = %s\n",
|
||||||
face->fsCsb[0], face->file);
|
face->fs.fsCsb[0], face->file);
|
||||||
return DEFAULT_CHARSET;
|
return DEFAULT_CHARSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,7 +1076,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!FontList) /* No fonts installed */
|
if(!FontList || !have_installed_roman_font) /* No fonts installed */
|
||||||
{
|
{
|
||||||
TRACE("No fonts installed\n");
|
TRACE("No fonts installed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1004,7 +1126,7 @@ 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->fsCsb[0]) || !csi.fs.fsCsb[0])
|
if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,7 +1142,7 @@ 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->fsCsb[0]) || !csi.fs.fsCsb[0])
|
if((csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]) || !csi.fs.fsCsb[0])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1049,14 +1171,14 @@ not_found:
|
||||||
strcpyW(lf.lfFaceName, defSans);
|
strcpyW(lf.lfFaceName, defSans);
|
||||||
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->fsCsb[0]))
|
(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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->fsCsb[0])
|
if(csi.fs.fsCsb[0] & family->FirstFace->fs.fsCsb[0])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1080,6 +1202,8 @@ not_found:
|
||||||
if(bd && !face->Bold) ret->fake_bold = TRUE;
|
if(bd && !face->Bold) ret->fake_bold = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&ret->fs, &face->fs, sizeof(FONTSIGNATURE));
|
||||||
|
|
||||||
if(csi.fs.fsCsb[0])
|
if(csi.fs.fsCsb[0])
|
||||||
ret->charset = lf.lfCharSet;
|
ret->charset = lf.lfCharSet;
|
||||||
else
|
else
|
||||||
|
@ -1174,6 +1298,8 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
font->name = strdupW(face->family->FamilyName);
|
||||||
|
|
||||||
memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
|
memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW));
|
||||||
|
|
||||||
size = WineEngGetOutlineTextMetrics(font, 0, NULL);
|
size = WineEngGetOutlineTextMetrics(font, 0, NULL);
|
||||||
|
@ -1252,17 +1378,31 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc,
|
||||||
DWORD type, ret = 1;
|
DWORD type, ret = 1;
|
||||||
FONTSIGNATURE fs;
|
FONTSIGNATURE fs;
|
||||||
CHARSETINFO csi;
|
CHARSETINFO csi;
|
||||||
|
LOGFONTW lf;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
|
TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
|
||||||
|
|
||||||
if(plf->lfFaceName[0]) {
|
if(plf->lfFaceName[0]) {
|
||||||
|
FontSubst *psub;
|
||||||
|
for(psub = substlist; psub; psub = psub->next)
|
||||||
|
if(!strcmpiW(plf->lfFaceName, psub->from.name) &&
|
||||||
|
(psub->from.charset == -1 ||
|
||||||
|
psub->from.charset == plf->lfCharSet))
|
||||||
|
break;
|
||||||
|
if(psub) {
|
||||||
|
TRACE("substituting %s -> %s\n", debugstr_w(plf->lfFaceName),
|
||||||
|
debugstr_w(psub->to.name));
|
||||||
|
memcpy(&lf, plf, sizeof(lf));
|
||||||
|
strcpyW(lf.lfFaceName, psub->to.name);
|
||||||
|
plf = &lf;
|
||||||
|
}
|
||||||
for(family = FontList; family; family = family->next) {
|
for(family = FontList; family; family = family->next) {
|
||||||
if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
|
if(!strcmpiW(plf->lfFaceName, family->FamilyName)) {
|
||||||
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->fsCsb[0] & (1L << i)) {
|
if(face->fs.fsCsb[0] & (1L << i)) {
|
||||||
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,
|
||||||
|
@ -1294,7 +1434,7 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc,
|
||||||
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->fsCsb[0] & (1L << i)) {
|
if(family->FirstFace->fs.fsCsb[0] & (1L << i)) {
|
||||||
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,
|
||||||
|
@ -1516,6 +1656,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix);
|
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpmat) pFT_Outline_Transform(&ft_face->glyph->outline, (FT_Matrix *)lpmat);
|
||||||
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
||||||
|
|
||||||
/* Note: FreeType will only set 'black' bits for us. */
|
/* Note: FreeType will only set 'black' bits for us. */
|
||||||
|
@ -1557,6 +1698,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix);
|
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpmat) pFT_Outline_Transform(&ft_face->glyph->outline, (FT_Matrix *)lpmat);
|
||||||
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
||||||
|
|
||||||
pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
|
pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
|
||||||
|
@ -1595,6 +1737,8 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
|
|
||||||
if(buflen == 0) buf = NULL;
|
if(buflen == 0) buf = NULL;
|
||||||
|
|
||||||
|
if (lpmat) pFT_Outline_Transform(outline, (FT_Matrix *)lpmat);
|
||||||
|
|
||||||
for(contour = 0; contour < outline->n_contours; contour++) {
|
for(contour = 0; contour < outline->n_contours; contour++) {
|
||||||
pph_start = needed;
|
pph_start = needed;
|
||||||
pph = (TTPOLYGONHEADER *)((char *)buf + needed);
|
pph = (TTPOLYGONHEADER *)((char *)buf + needed);
|
||||||
|
@ -1671,6 +1815,8 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
|
||||||
FT_Vector cubic_control[4];
|
FT_Vector cubic_control[4];
|
||||||
if(buflen == 0) buf = NULL;
|
if(buflen == 0) buf = NULL;
|
||||||
|
|
||||||
|
if (lpmat) pFT_Outline_Transform(outline, (FT_Matrix *)lpmat);
|
||||||
|
|
||||||
for(contour = 0; contour < outline->n_contours; contour++) {
|
for(contour = 0; contour < outline->n_contours; contour++) {
|
||||||
pph_start = needed;
|
pph_start = needed;
|
||||||
pph = (TTPOLYGONHEADER *)((char *)buf + needed);
|
pph = (TTPOLYGONHEADER *)((char *)buf + needed);
|
||||||
|
@ -1807,11 +1953,8 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
|
||||||
|
|
||||||
needed = sizeof(*potm);
|
needed = sizeof(*potm);
|
||||||
|
|
||||||
lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0)
|
lenfam = (strlenW(font->name) + 1) * sizeof(WCHAR);
|
||||||
* sizeof(WCHAR);
|
family_nameW = strdupW(font->name);
|
||||||
family_nameW = HeapAlloc(GetProcessHeap(), 0, lenfam);
|
|
||||||
MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1,
|
|
||||||
family_nameW, lenfam);
|
|
||||||
|
|
||||||
lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
|
lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0)
|
||||||
* sizeof(WCHAR);
|
* sizeof(WCHAR);
|
||||||
|
@ -2030,8 +2173,9 @@ BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar,
|
||||||
TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
|
TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer);
|
||||||
|
|
||||||
for(c = firstChar; c <= lastChar; c++) {
|
for(c = firstChar; c <= lastChar; c++) {
|
||||||
WineEngGetGlyphOutline(font, c, GGO_METRICS, &gm, 0, NULL, NULL);
|
|
||||||
glyph_index = get_glyph_index(font, c);
|
glyph_index = get_glyph_index(font, c);
|
||||||
|
WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
|
||||||
|
&gm, 0, NULL, NULL);
|
||||||
buffer[c - firstChar] = font->gm[glyph_index].adv;
|
buffer[c - firstChar] = font->gm[glyph_index].adv;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2057,9 +2201,9 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count,
|
||||||
size->cy = tm.tmHeight;
|
size->cy = tm.tmHeight;
|
||||||
|
|
||||||
for(idx = 0; idx < count; idx++) {
|
for(idx = 0; idx < count; idx++) {
|
||||||
WineEngGetGlyphOutline(font, wstr[idx], GGO_METRICS, &gm, 0, NULL,
|
|
||||||
NULL);
|
|
||||||
glyph_index = get_glyph_index(font, wstr[idx]);
|
glyph_index = get_glyph_index(font, wstr[idx]);
|
||||||
|
WineEngGetGlyphOutline(font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX,
|
||||||
|
&gm, 0, NULL, NULL);
|
||||||
size->cx += font->gm[glyph_index].adv;
|
size->cx += font->gm[glyph_index].adv;
|
||||||
}
|
}
|
||||||
TRACE("return %ld,%ld\n", size->cx, size->cy);
|
TRACE("return %ld,%ld\n", size->cx, size->cy);
|
||||||
|
@ -2101,8 +2245,6 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
|
||||||
DWORD cbData)
|
DWORD cbData)
|
||||||
{
|
{
|
||||||
FT_Face ft_face = font->ft_face;
|
FT_Face ft_face = font->ft_face;
|
||||||
TT_Face tt_face;
|
|
||||||
SFNT_Interface *sfnt;
|
|
||||||
DWORD len;
|
DWORD len;
|
||||||
FT_Error err;
|
FT_Error err;
|
||||||
|
|
||||||
|
@ -2112,18 +2254,6 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
|
||||||
if(!FT_IS_SFNT(ft_face))
|
if(!FT_IS_SFNT(ft_face))
|
||||||
return GDI_ERROR;
|
return GDI_ERROR;
|
||||||
|
|
||||||
tt_face = (TT_Face) ft_face;
|
|
||||||
if (FT_Version.major==2 && FT_Version.minor==0)
|
|
||||||
{
|
|
||||||
/* 2.0.x */
|
|
||||||
sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* A field was added in the middle of the structure in 2.1.x */
|
|
||||||
sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!buf || !cbData)
|
if(!buf || !cbData)
|
||||||
len = 0;
|
len = 0;
|
||||||
else
|
else
|
||||||
|
@ -2134,7 +2264,24 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
|
||||||
(table >> 8 & 0xff00) | (table << 8 & 0xff0000);
|
(table >> 8 & 0xff00) | (table << 8 & 0xff0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the FT_Load_Sfnt_Table function is there we'll use it */
|
||||||
|
if(pFT_Load_Sfnt_Table)
|
||||||
|
err = pFT_Load_Sfnt_Table(ft_face, table, offset, buf, &len);
|
||||||
|
else { /* Do it the hard way */
|
||||||
|
TT_Face tt_face = (TT_Face) ft_face;
|
||||||
|
SFNT_Interface *sfnt;
|
||||||
|
if (FT_Version.major==2 && FT_Version.minor==0)
|
||||||
|
{
|
||||||
|
/* 2.0.x */
|
||||||
|
sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A field was added in the middle of the structure in 2.1.x */
|
||||||
|
sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
|
||||||
|
}
|
||||||
err = sfnt->load_any(tt_face, table, offset, buf, &len);
|
err = sfnt->load_any(tt_face, table, offset, buf, &len);
|
||||||
|
}
|
||||||
if(err) {
|
if(err) {
|
||||||
TRACE("Can't find table %08lx.\n", table);
|
TRACE("Can't find table %08lx.\n", table);
|
||||||
return GDI_ERROR;
|
return GDI_ERROR;
|
||||||
|
@ -2155,6 +2302,11 @@ INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
|
||||||
return strlenW(font->name) + 1;
|
return strlenW(font->name) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
|
||||||
|
{
|
||||||
|
if (fs) memcpy(fs, &font->fs, sizeof(FONTSIGNATURE));
|
||||||
|
return font->charset;
|
||||||
|
}
|
||||||
|
|
||||||
#else /* HAVE_FREETYPE */
|
#else /* HAVE_FREETYPE */
|
||||||
|
|
||||||
|
@ -2248,4 +2400,11 @@ INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
|
||||||
FIXME(":stub\n");
|
FIXME(":stub\n");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags)
|
||||||
|
{
|
||||||
|
FIXME(":stub\n");
|
||||||
|
return DEFAULT_CHARSET;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_FREETYPE */
|
#endif /* HAVE_FREETYPE */
|
||||||
|
|
|
@ -483,6 +483,7 @@ extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
|
||||||
LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
|
LPGLYPHMETRICS, DWORD buflen, LPVOID buf,
|
||||||
const MAT2*);
|
const MAT2*);
|
||||||
extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
|
extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
|
||||||
|
extern UINT WineEngGetTextCharsetInfo(GdiFont font, LPFONTSIGNATURE fs, DWORD flags);
|
||||||
extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
|
extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE);
|
||||||
extern BOOL WineEngGetTextExtentPointI(GdiFont, const WORD *, INT, LPSIZE);
|
extern BOOL WineEngGetTextExtentPointI(GdiFont, const WORD *, INT, LPSIZE);
|
||||||
extern INT WineEngGetTextFace(GdiFont, INT, LPWSTR);
|
extern INT WineEngGetTextFace(GdiFont, INT, LPWSTR);
|
||||||
|
|
|
@ -2235,3 +2235,33 @@ BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
|
||||||
{
|
{
|
||||||
return WineEngRemoveFontResourceEx(str, fl, pdv);
|
return WineEngRemoveFontResourceEx(str, fl, pdv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetTextCharset (GDI32.@)
|
||||||
|
*/
|
||||||
|
UINT WINAPI GetTextCharset(HDC hdc)
|
||||||
|
{
|
||||||
|
/* MSDN docs say this is equivalent */
|
||||||
|
return GetTextCharsetInfo(hdc, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* GetTextCharsetInfo (GDI32.@)
|
||||||
|
*/
|
||||||
|
UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
|
||||||
|
{
|
||||||
|
UINT ret = DEFAULT_CHARSET;
|
||||||
|
DC *dc = DC_GetDCPtr(hdc);
|
||||||
|
|
||||||
|
if (!dc) goto done;
|
||||||
|
|
||||||
|
if (dc->gdiFont)
|
||||||
|
ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
|
||||||
|
|
||||||
|
GDI_ReleaseObj(hdc);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (ret == DEFAULT_CHARSET && fs)
|
||||||
|
memset(fs, 0, sizeof(FONTSIGNATURE));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -206,61 +206,6 @@ BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetTextCharset [GDI32.@] Gets character set for font in DC
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* Should it return a UINT32 instead of an INT32?
|
|
||||||
* => YES, as GetTextCharsetInfo returns UINT32
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: Character set identifier
|
|
||||||
* Failure: DEFAULT_CHARSET
|
|
||||||
*/
|
|
||||||
UINT WINAPI GetTextCharset(
|
|
||||||
HDC hdc) /* [in] Handle to device context */
|
|
||||||
{
|
|
||||||
/* MSDN docs say this is equivalent */
|
|
||||||
return GetTextCharsetInfo(hdc, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* GetTextCharsetInfo [GDI32.@] Gets character set for font
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* Should csi be an LPFONTSIGNATURE instead of an LPCHARSETINFO?
|
|
||||||
* Should it return a UINT32 instead of an INT32?
|
|
||||||
* => YES and YES, from win32.hlp from Borland
|
|
||||||
*
|
|
||||||
* This returns the actual charset selected by the driver rather than the
|
|
||||||
* value in lf.lfCharSet during CreateFont, to get that use
|
|
||||||
* GetObject(GetCurrentObject(...),...)
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: Character set identifier
|
|
||||||
* Failure: DEFAULT_CHARSET
|
|
||||||
*/
|
|
||||||
UINT WINAPI GetTextCharsetInfo(
|
|
||||||
HDC hdc, /* [in] Handle to device context */
|
|
||||||
LPFONTSIGNATURE fs, /* [out] Pointer to struct to receive data */
|
|
||||||
DWORD flags) /* [in] Reserved - must be 0 */
|
|
||||||
{
|
|
||||||
UINT charSet = DEFAULT_CHARSET;
|
|
||||||
CHARSETINFO csinfo;
|
|
||||||
TEXTMETRICW tm;
|
|
||||||
|
|
||||||
if(!GetTextMetricsW(hdc, &tm)) return DEFAULT_CHARSET;
|
|
||||||
charSet = tm.tmCharSet;
|
|
||||||
|
|
||||||
if (fs != NULL) {
|
|
||||||
if (!TranslateCharsetInfo((LPDWORD)charSet, &csinfo, TCI_SRCCHARSET))
|
|
||||||
return DEFAULT_CHARSET;
|
|
||||||
memcpy(fs, &csinfo.fs, sizeof(FONTSIGNATURE));
|
|
||||||
}
|
|
||||||
return charSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* PolyTextOutA (GDI32.@)
|
* PolyTextOutA (GDI32.@)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue