Commit 8da26fb2 authored by Huw D M Davies's avatar Huw D M Davies Committed by Alexandre Julliard

- Implement AddFontResource*, add stubs for RemoveFontResource*.

- Add support for GGO_BEZIER and a few bug fixes for GGO_NATIVE. - Much better support for non ansi charsets in font matching. - Proper implementation of GetTextFace for gdi font. - Load fonts that are listed in the registry but aren't in %WINDOWSDIR%\fonts. - Revert TranslateCharsetInfo to use codepage 1252 with ANSI_CHARSET. - Add support for VIETNAMESE_CHARSET and SYMBOL_CHARSET.
parent 09b4c500
...@@ -104,6 +104,7 @@ MAKE_FUNCPTR(FT_Vector_Rotate) ...@@ -104,6 +104,7 @@ MAKE_FUNCPTR(FT_Vector_Rotate)
typedef struct tagFace { typedef struct tagFace {
WCHAR *StyleName; WCHAR *StyleName;
char *file; char *file;
FT_Long face_index;
BOOL Italic; BOOL Italic;
BOOL Bold; BOOL Bold;
DWORD fsCsb[2]; /* codepage bitfield from FONTSIGNATURE */ DWORD fsCsb[2]; /* codepage bitfield from FONTSIGNATURE */
...@@ -126,6 +127,7 @@ typedef struct { ...@@ -126,6 +127,7 @@ typedef struct {
struct tagGdiFont { struct tagGdiFont {
FT_Face ft_face; FT_Face ft_face;
LPWSTR name;
int charset; int charset;
BOOL fake_italic; BOOL fake_italic;
BOOL fake_bold; BOOL fake_bold;
...@@ -135,6 +137,7 @@ struct tagGdiFont { ...@@ -135,6 +137,7 @@ struct tagGdiFont {
HFONT hfont; HFONT hfont;
SHORT yMax; SHORT yMax;
SHORT yMin; SHORT yMin;
OUTLINETEXTMETRICW *potm;
struct tagGdiFont *next; struct tagGdiFont *next;
}; };
...@@ -157,11 +160,16 @@ static WCHAR HelvW[] = {'H','e','l','v','\0'}; ...@@ -157,11 +160,16 @@ static WCHAR HelvW[] = {'H','e','l','v','\0'};
static WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'}; static WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'};
static WCHAR BalticW[] = {'B','a','l','t','i','c','\0'}; static WCHAR BalticW[] = {'B','a','l','t','i','c','\0'};
static WCHAR CHINESE_BIG5W[] = {'C','H','I','N','E','S','E','_','B','I','G','5','\0'};
static WCHAR CHINESE_GB2312W[] = {'C','H','I','N','E','S','E','_','G','B','2','3','1','2','\0'};
static WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ', static WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ',
'E','u','r','o','p','e','a','n','\0'}; 'E','u','r','o','p','e','a','n','\0'};
static WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'}; static WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'};
static WCHAR GreekW[] = {'G','r','e','e','k','\0'}; static WCHAR GreekW[] = {'G','r','e','e','k','\0'};
static WCHAR HangulW[] = {'H','a','n','g','u','l','\0'};
static WCHAR Hangul_Johab_W[] = {'H','a','n','g','u','l','(','J','o','h','a','b',')','\0'};
static WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'}; static WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'};
static WCHAR JapaneseW[] = {'J','a','p','a','n','e','s','e','\0'};
static WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'}; static WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'};
static WCHAR ThaiW[] = {'T','h','a','i','\0'}; static WCHAR ThaiW[] = {'T','h','a','i','\0'};
static WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'}; static WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'};
...@@ -180,7 +188,12 @@ static WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits ...@@ -180,7 +188,12 @@ static WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits
VietnameseW, /*08*/ VietnameseW, /*08*/
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
ThaiW, ThaiW,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*23*/ JapaneseW,
CHINESE_GB2312W,
HangulW,
CHINESE_BIG5W,
Hangul_Johab_W,
NULL, NULL, /*23*/
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
SymbolW /*31*/ SymbolW /*31*/
}; };
...@@ -208,90 +221,99 @@ static BOOL AddFontFileToList(char *file) ...@@ -208,90 +221,99 @@ static BOOL AddFontFileToList(char *file)
Family **insert = &FontList; Family **insert = &FontList;
Face **insertface; Face **insertface;
FT_Error err; FT_Error err;
FT_Long face_index = 0, num_faces;
int i; int i;
TRACE("Loading font file %s\n", debugstr_a(file)); do {
if((err = pFT_New_Face(library, file, 0, &ft_face)) != 0) { TRACE("Loading font file %s index %ld\n", debugstr_a(file), face_index);
ERR("Unable to load font file %s err = %x\n", debugstr_a(file), err); if((err = pFT_New_Face(library, file, face_index, &ft_face)) != 0) {
return FALSE; ERR("Unable to load font file %s err = %x\n", debugstr_a(file), err);
} return FALSE;
}
if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */
pFT_Done_Face(ft_face);
return FALSE;
}
len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0);
FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, FamilyW, len);
while(family) {
if(!strcmpW(family->FamilyName, FamilyW))
break;
insert = &family->next;
family = family->next;
}
if(!family) {
family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
family->FamilyName = FamilyW;
family->FirstFace = NULL;
family->next = NULL;
} else {
HeapFree(GetProcessHeap(), 0, FamilyW);
}
len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
for(insertface = &family->FirstFace; *insertface; if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */
insertface = &(*insertface)->next) { pFT_Done_Face(ft_face);
if(!strcmpW((*insertface)->StyleName, StyleW)) { return FALSE;
WARN("Already loaded font %s %s\n", debugstr_w(family->FamilyName), }
debugstr_w(StyleW)); if(!pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2) ||
HeapFree(GetProcessHeap(), 0, StyleW); !pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea)) {
TRACE("Font file %s lacks either an OS2 or HHEA table.\n"
"Skipping this font.\n", debugstr_a(file));
pFT_Done_Face(ft_face); pFT_Done_Face(ft_face);
return FALSE; return FALSE;
} }
}
*insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
(*insertface)->StyleName = StyleW;
(*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
strcpy((*insertface)->file, file);
(*insertface)->next = NULL;
(*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
(*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0);
if(pOS2) { FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
(*insertface)->fsCsb[0] = pOS2->ulCodePageRange1; MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, FamilyW, len);
(*insertface)->fsCsb[1] = pOS2->ulCodePageRange2;
} else { while(family) {
(*insertface)->fsCsb[0] = (*insertface)->fsCsb[1] = 0; if(!strcmpW(family->FamilyName, FamilyW))
}
TRACE("fsCsb = %08lx %08lx\n", (*insertface)->fsCsb[0], (*insertface)->fsCsb[1]);
if((*insertface)->fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
for(i = 0; i < ft_face->num_charmaps &&
!(*insertface)->fsCsb[0]; i++) {
switch(ft_face->charmaps[i]->encoding) {
case ft_encoding_unicode:
(*insertface)->fsCsb[0] = 1;
break;
case ft_encoding_symbol:
(*insertface)->fsCsb[0] = 1L << 31;
break;
default:
break; break;
} insert = &family->next;
family = family->next;
}
if(!family) {
family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family));
family->FamilyName = FamilyW;
family->FirstFace = NULL;
family->next = NULL;
} else {
HeapFree(GetProcessHeap(), 0, FamilyW);
} }
}
pFT_Done_Face(ft_face);
TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0);
debugstr_w(StyleW)); StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len);
for(insertface = &family->FirstFace; *insertface;
insertface = &(*insertface)->next) {
if(!strcmpW((*insertface)->StyleName, StyleW)) {
TRACE("Already loaded font %s %s\n", debugstr_w(family->FamilyName),
debugstr_w(StyleW));
HeapFree(GetProcessHeap(), 0, StyleW);
pFT_Done_Face(ft_face);
return FALSE;
}
}
*insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface));
(*insertface)->StyleName = StyleW;
(*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1);
strcpy((*insertface)->file, file);
(*insertface)->face_index = face_index;
(*insertface)->next = NULL;
(*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
(*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0;
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
if(pOS2) {
(*insertface)->fsCsb[0] = pOS2->ulCodePageRange1;
(*insertface)->fsCsb[1] = pOS2->ulCodePageRange2;
} else {
(*insertface)->fsCsb[0] = (*insertface)->fsCsb[1] = 0;
}
TRACE("fsCsb = %08lx %08lx\n", (*insertface)->fsCsb[0], (*insertface)->fsCsb[1]);
if((*insertface)->fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */
for(i = 0; i < ft_face->num_charmaps &&
!(*insertface)->fsCsb[0]; i++) {
switch(ft_face->charmaps[i]->encoding) {
case ft_encoding_unicode:
(*insertface)->fsCsb[0] = 1;
break;
case ft_encoding_symbol:
(*insertface)->fsCsb[0] = 1L << 31;
break;
default:
break;
}
}
}
num_faces = ft_face->num_faces;
pFT_Done_Face(ft_face);
TRACE("Added font %s %s\n", debugstr_w(family->FamilyName),
debugstr_w(StyleW));
} while(num_faces > ++face_index);
return TRUE; return TRUE;
} }
...@@ -323,6 +345,15 @@ static void DumpSubstList(void) ...@@ -323,6 +345,15 @@ static void DumpSubstList(void)
return; return;
} }
static LPWSTR strdupW(LPWSTR p)
{
LPWSTR ret;
DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
ret = HeapAlloc(GetProcessHeap(), 0, len);
memcpy(ret, p, len);
return ret;
}
static void split_subst_info(NameCs *nc, LPSTR str) static void split_subst_info(NameCs *nc, LPSTR str)
{ {
CHAR *p = strrchr(str, ','); CHAR *p = strrchr(str, ',');
...@@ -437,7 +468,38 @@ static BOOL ReadFontDir(char *dirname) ...@@ -437,7 +468,38 @@ static BOOL ReadFontDir(char *dirname)
return TRUE; return TRUE;
} }
/*************************************************************
* WineEngAddFontResourceEx
*
*/
INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
{
if (ft_handle) /* do it only if we have freetype up and running */
{
DWORD len = WideCharToMultiByte(CP_ACP, 0, file, -1, NULL, 0, NULL, NULL);
LPSTR fileA = HeapAlloc(GetProcessHeap(), 0, len);
char unixname[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, file, -1, fileA, len, NULL, NULL);
if(flags)
FIXME("Ignoring flags %lx\n", flags);
if(wine_get_unix_file_name(fileA, unixname, sizeof(unixname)))
AddFontFileToList(unixname);
HeapFree(GetProcessHeap(), 0, fileA);
}
return 1;
}
/*************************************************************
* WineEngRemoveFontResourceEx
*
*/
BOOL WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
{
FIXME(":stub\n");
return TRUE;
}
/************************************************************* /*************************************************************
* WineEngInit * WineEngInit
...@@ -495,14 +557,46 @@ BOOL WineEngInit(void) ...@@ -495,14 +557,46 @@ BOOL WineEngInit(void)
if(pFT_Init_FreeType(&library) != 0) { if(pFT_Init_FreeType(&library) != 0) {
ERR("Can't init FreeType library\n"); ERR("Can't init FreeType library\n");
wine_dlclose(ft_handle, NULL, 0); wine_dlclose(ft_handle, NULL, 0);
ft_handle = NULL;
return FALSE; return FALSE;
} }
/* load in the fonts from %WINDOWSDIR%\\Fonts first of all */ /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */
GetWindowsDirectoryA(windowsdir, sizeof(windowsdir)); GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
strcat(windowsdir, "\\Fonts"); strcat(windowsdir, "\\Fonts");
wine_get_unix_file_name(windowsdir, unixname, sizeof(unixname)); if(wine_get_unix_file_name(windowsdir, unixname, sizeof(unixname)))
ReadFontDir(unixname); ReadFontDir(unixname);
/* now look under HKLM\Software\Microsoft\Windows\CurrentVersion\Fonts
for any fonts not installed in %WINDOWSDIR%\Fonts. They will have their
full path as the entry */
if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts",
&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);
data = HeapAlloc(GetProcessHeap(), 0, datalen);
dlen = datalen;
vlen = valuelen;
while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
&dlen) == ERROR_SUCCESS) {
if(((LPSTR)data)[1] == ':')
if(wine_get_unix_file_name((LPSTR)data, unixname, sizeof(unixname)))
AddFontFileToList(unixname);
/* reset dlen and vlen */
dlen = datalen;
vlen = valuelen;
}
HeapFree(GetProcessHeap(), 0, data);
HeapFree(GetProcessHeap(), 0, value);
RegCloseKey(hkey);
}
/* then look in any directories that we've specified in the config file */ /* then look in any directories that we've specified in the config file */
if(RegOpenKeyA(HKEY_LOCAL_MACHINE, if(RegOpenKeyA(HKEY_LOCAL_MACHINE,
...@@ -518,6 +612,7 @@ BOOL WineEngInit(void) ...@@ -518,6 +612,7 @@ BOOL WineEngInit(void)
dlen = datalen; dlen = datalen;
vlen = valuelen; vlen = valuelen;
i = 0;
while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data, while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data,
&dlen) == ERROR_SUCCESS) { &dlen) == ERROR_SUCCESS) {
TRACE("Got %s=%s\n", value, (LPSTR)data); TRACE("Got %s=%s\n", value, (LPSTR)data);
...@@ -542,6 +637,7 @@ sym_not_found: ...@@ -542,6 +637,7 @@ sym_not_found:
"FreeType to at least version 2.0.5.\n" "FreeType to at least version 2.0.5.\n"
"http://www.freetype.org\n"); "http://www.freetype.org\n");
wine_dlclose(ft_handle, NULL, 0); wine_dlclose(ft_handle, NULL, 0);
ft_handle = NULL;
return FALSE; return FALSE;
} }
...@@ -580,13 +676,13 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height) ...@@ -580,13 +676,13 @@ 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, LONG height) static FT_Face OpenFontFile(GdiFont font, char *file, FT_Long face_index, LONG height)
{ {
FT_Error err; FT_Error err;
FT_Face ft_face; FT_Face ft_face;
LONG ppem; LONG ppem;
err = pFT_New_Face(library, file, 0, &ft_face); err = pFT_New_Face(library, file, face_index, &ft_face);
if(err) { if(err) {
ERR("FT_New_Face rets %d\n", err); ERR("FT_New_Face rets %d\n", err);
return 0; return 0;
...@@ -605,16 +701,31 @@ static FT_Face OpenFontFile(GdiFont font, char *file, LONG height) ...@@ -605,16 +701,31 @@ static FT_Face OpenFontFile(GdiFont font, char *file, LONG height)
return ft_face; return ft_face;
} }
static int get_nearest_charset(Face *face, int lfcharset)
{
CHARSETINFO csi;
TranslateCharsetInfo((DWORD*)lfcharset, &csi, TCI_SRCCHARSET);
if(csi.fs.fsCsb[0] & face->fsCsb[0]) return lfcharset; static int get_nearest_charset(Face *face)
{
if(face->fsCsb[0] & 0x1) return ANSI_CHARSET; /* Only get here if lfCharSet == DEFAULT_CHARSET or we couldn't find
a single face with the requested charset. The idea is to check if
the selected font supports the current ANSI codepage, if it does
return the corresponding charset, else return the first charset */
if(face->fsCsb[0] & (1L << 31)) return SYMBOL_CHARSET; CHARSETINFO csi;
int acp = GetACP(), i;
DWORD fs0;
if(TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE))
if(csi.fs.fsCsb[0] & face->fsCsb[0])
return csi.ciCharset;
for(i = 0; i < 32; i++) {
fs0 = 1L << i;
if(face->fsCsb[0] & fs0) {
if(TranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
return csi.ciCharset;
else
FIXME("TCI failing on %lx\n", fs0);
}
}
FIXME("returning DEFAULT_CHARSET face->fsCsb[0] = %08lx file = %s\n", FIXME("returning DEFAULT_CHARSET face->fsCsb[0] = %08lx file = %s\n",
face->fsCsb[0], face->file); face->fsCsb[0], face->file);
...@@ -628,12 +739,15 @@ static GdiFont alloc_font(void) ...@@ -628,12 +739,15 @@ static GdiFont alloc_font(void)
ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
ret->gmsize * sizeof(*ret->gm)); ret->gmsize * sizeof(*ret->gm));
ret->next = NULL; ret->next = NULL;
ret->potm = NULL;
return ret; return ret;
} }
static void free_font(GdiFont font) static void free_font(GdiFont font)
{ {
if (font->ft_face) pFT_Done_Face(font->ft_face); if (font->ft_face) pFT_Done_Face(font->ft_face);
if (font->potm) HeapFree(GetProcessHeap(), 0, font->potm);
if (font->name) HeapFree(GetProcessHeap(), 0, font->name);
HeapFree(GetProcessHeap(), 0, font->gm); HeapFree(GetProcessHeap(), 0, font->gm);
HeapFree(GetProcessHeap(), 0, font); HeapFree(GetProcessHeap(), 0, font);
} }
...@@ -798,6 +912,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -798,6 +912,7 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
Family *family = NULL; Family *family = NULL;
BOOL bd, it; BOOL bd, it;
LOGFONTW lf; LOGFONTW lf;
CHARSETINFO csi;
if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL; if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL;
...@@ -822,6 +937,26 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -822,6 +937,26 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
ret = alloc_font(); ret = alloc_font();
/* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
SYMBOL_CHARSET so that Symbol gets picked irrespective of the
original value lfCharSet. Note this is a special case for
Symbol and doesn't happen at least for "Wingdings*" */
if(!strcmpiW(lf.lfFaceName, SymbolW))
lf.lfCharSet = SYMBOL_CHARSET;
if(!TranslateCharsetInfo((DWORD*)(INT)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
switch(lf.lfCharSet) {
case DEFAULT_CHARSET:
csi.fs.fsCsb[0] = 0;
break;
default:
FIXME("Untranslated charset %d\n", lf.lfCharSet);
csi.fs.fsCsb[0] = 0;
break;
}
}
if(lf.lfFaceName[0] != '\0') { if(lf.lfFaceName[0] != '\0') {
FontSubst *psub; FontSubst *psub;
for(psub = substlist; psub; psub = psub->next) for(psub = substlist; psub; psub = psub->next)
...@@ -835,9 +970,16 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -835,9 +970,16 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont)
strcpyW(lf.lfFaceName, psub->to.name); strcpyW(lf.lfFaceName, psub->to.name);
} }
/* We want a match on name and charset or just name if
charset was DEFAULT_CHARSET. If the latter then
we fixup the returned charset later in get_nearest_charset
where we'll either use the charset of the current ansi codepage
or if that's unavailable the first charset that the font supports.
*/
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))
break; if((csi.fs.fsCsb[0] & family->FirstFace->fsCsb[0]) || !csi.fs.fsCsb[0])
break;
} }
if(!family) { /* do other aliases here */ if(!family) { /* do other aliases here */
...@@ -852,13 +994,24 @@ GdiFont WineEngCreateFontInstance(DC *dc, HFONT hfont) ...@@ -852,13 +994,24 @@ 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))
break; if((csi.fs.fsCsb[0] & family->FirstFace->fsCsb[0]) || !csi.fs.fsCsb[0])
break;
} }
} }
} }
not_found: not_found:
if(!family) { if(!family) {
/* If requested charset was DEFAULT_CHARSET then try using charset
corresponding to the current ansi codepage */
if(!csi.fs.fsCsb[0]) {
INT acp = GetACP();
if(!TranslateCharsetInfo((DWORD*)acp, &csi, TCI_SRCCODEPAGE)) {
FIXME("TCI failed on codepage %d\n", acp);
csi.fs.fsCsb[0] = 0;
} else
lf.lfCharSet = csi.ciCharset;
}
if(lf.lfPitchAndFamily & FIXED_PITCH || if(lf.lfPitchAndFamily & FIXED_PITCH ||
lf.lfPitchAndFamily & FF_MODERN) lf.lfPitchAndFamily & FF_MODERN)
strcpyW(lf.lfFaceName, defFixed); strcpyW(lf.lfFaceName, defFixed);
...@@ -869,13 +1022,22 @@ not_found: ...@@ -869,13 +1022,22 @@ not_found:
else else
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]))
break;
}
}
if(!family) {
for(family = FontList; family; family = family->next) {
if(csi.fs.fsCsb[0] & family->FirstFace->fsCsb[0])
break; break;
} }
} }
if(!family) { if(!family) {
family = FontList; family = FontList;
csi.fs.fsCsb[0] = 0;
FIXME("just using first face for now\n"); FIXME("just using first face for now\n");
} }
...@@ -891,12 +1053,16 @@ not_found: ...@@ -891,12 +1053,16 @@ not_found:
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;
} }
ret->charset = get_nearest_charset(face, lf.lfCharSet);
if(csi.fs.fsCsb[0])
ret->charset = lf.lfCharSet;
else
ret->charset = get_nearest_charset(face);
TRACE("Choosen %s %s\n", debugstr_w(family->FamilyName), TRACE("Choosen %s %s\n", debugstr_w(family->FamilyName),
debugstr_w(face->StyleName)); debugstr_w(face->StyleName));
ret->ft_face = OpenFontFile(ret, face->file, ret->ft_face = OpenFontFile(ret, face->file, face->face_index,
INTERNAL_YWSTODS(dc,lf.lfHeight)); INTERNAL_YWSTODS(dc,lf.lfHeight));
if (!ret->ft_face) if (!ret->ft_face)
{ {
...@@ -907,6 +1073,7 @@ not_found: ...@@ -907,6 +1073,7 @@ not_found:
if(ret->charset == SYMBOL_CHARSET) if(ret->charset == SYMBOL_CHARSET)
pFT_Select_Charmap(ret->ft_face, ft_encoding_symbol); pFT_Select_Charmap(ret->ft_face, ft_encoding_symbol);
ret->orientation = lf.lfOrientation; ret->orientation = lf.lfOrientation;
ret->name = strdupW(family->FamilyName);
TRACE("caching: gdiFont=%p hfont=%x\n", ret, hfont); TRACE("caching: gdiFont=%p hfont=%x\n", ret, hfont);
ret->hfont = hfont; ret->hfont = hfont;
...@@ -966,7 +1133,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, ...@@ -966,7 +1133,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf,
UINT size; UINT size;
GdiFont font = alloc_font(); GdiFont font = alloc_font();
if (!(font->ft_face = OpenFontFile(font, face->file, 100))) if (!(font->ft_face = OpenFontFile(font, face->file, face->face_index, 100)))
{ {
free_font(font); free_font(font);
return; return;
...@@ -1053,6 +1220,7 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, ...@@ -1053,6 +1220,7 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc,
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]) {
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)) {
...@@ -1175,6 +1343,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1175,6 +1343,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
FT_Error err; FT_Error err;
INT left, right, top = 0, bottom = 0; INT left, right, top = 0, bottom = 0;
FT_Angle angle = 0; FT_Angle angle = 0;
FT_Int load_flags = FT_LOAD_DEFAULT;
TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm, TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm,
buflen, buf, lpmat); buflen, buf, lpmat);
...@@ -1196,7 +1365,10 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1196,7 +1365,10 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
} }
} }
err = pFT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); if(font->orientation || (format != GGO_METRICS && format != GGO_BITMAP))
load_flags |= FT_LOAD_NO_BITMAP;
err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
if(err) { if(err) {
FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err); FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err);
...@@ -1265,7 +1437,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1265,7 +1437,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
if(format == GGO_METRICS) if(format == GGO_METRICS)
return 1; /* FIXME */ return 1; /* FIXME */
if(ft_face->glyph->format != ft_glyph_format_outline) { if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP) {
FIXME("loaded a bitmap\n"); FIXME("loaded a bitmap\n");
return GDI_ERROR; return GDI_ERROR;
} }
...@@ -1278,26 +1450,48 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1278,26 +1450,48 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
needed = pitch * height; needed = pitch * height;
if(!buf || !buflen) break; if(!buf || !buflen) break;
ft_bitmap.width = width;
ft_bitmap.rows = height;
ft_bitmap.pitch = pitch;
ft_bitmap.pixel_mode = ft_pixel_mode_mono;
ft_bitmap.buffer = buf;
if(font->orientation) { switch(ft_face->glyph->format) {
FT_Matrix matrix; case ft_glyph_format_bitmap:
matrix.xx = matrix.yy = pFT_Cos(angle); {
matrix.xy = -pFT_Sin(angle); BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
matrix.yx = -matrix.xy; INT w = (ft_face->glyph->bitmap.width + 7) >> 3;
INT h = ft_face->glyph->bitmap.rows;
while(h--) {
memcpy(dst, src, w);
src += ft_face->glyph->bitmap.pitch;
dst += pitch;
}
break;
}
case ft_glyph_format_outline:
ft_bitmap.width = width;
ft_bitmap.rows = height;
ft_bitmap.pitch = pitch;
ft_bitmap.pixel_mode = ft_pixel_mode_mono;
ft_bitmap.buffer = buf;
if(font->orientation) {
FT_Matrix matrix;
matrix.xx = matrix.yy = pFT_Cos(angle);
matrix.xy = -pFT_Sin(angle);
matrix.yx = -matrix.xy;
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix);
}
pFT_Outline_Transform(&ft_face->glyph->outline, &matrix); 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. */
memset(buf, 0, needed);
pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap);
break;
/* Note: FreeType will only set 'black' bits for us. */ default:
memset(buf, 0, needed); FIXME("loaded glyph format %x\n", ft_face->glyph->format);
pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); return GDI_ERROR;
}
break; break;
case GGO_GRAY2_BITMAP: case GGO_GRAY2_BITMAP:
...@@ -1378,7 +1572,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1378,7 +1572,7 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
point++; point++;
while(point <= outline->contours[contour]) { while(point <= outline->contours[contour]) {
ppc = buf + needed; ppc = buf + needed;
type = (outline->tags[point] == FT_Curve_Tag_On) ? type = (outline->tags[point] & FT_Curve_Tag_On) ?
TT_PRIM_LINE : TT_PRIM_QSPLINE; TT_PRIM_LINE : TT_PRIM_QSPLINE;
cpfx = 0; cpfx = 0;
do { do {
...@@ -1387,13 +1581,16 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1387,13 +1581,16 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
cpfx++; cpfx++;
point++; point++;
} while(point <= outline->contours[contour] && } while(point <= outline->contours[contour] &&
outline->tags[point] == outline->tags[point-1]); (outline->tags[point] & FT_Curve_Tag_On) ==
/* At the end of a contour Windows adds the start point */ (outline->tags[point-1] & FT_Curve_Tag_On));
if(point > outline->contours[contour]) { /* At the end of a contour Windows adds the start point, but
only for Beziers */
if(point > outline->contours[contour] &&
!(outline->tags[point-1] & FT_Curve_Tag_On)) {
if(buf) if(buf)
FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]); FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
cpfx++; cpfx++;
} else if(outline->tags[point] == FT_Curve_Tag_On) { } else if(outline->tags[point] & FT_Curve_Tag_On) {
/* add closing pt for bezier */ /* add closing pt for bezier */
if(buf) if(buf)
FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
...@@ -1411,6 +1608,119 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1411,6 +1608,119 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
} }
break; break;
} }
case GGO_BEZIER:
{
/* Convert the quadratic Beziers to cubic Beziers.
The parametric eqn for a cubic Bezier is, from PLRM:
r(t) = at^3 + bt^2 + ct + r0
with the control points:
r1 = r0 + c/3
r2 = r1 + (c + b)/3
r3 = r0 + c + b + a
A quadratic Beizer has the form:
p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
So equating powers of t leads to:
r1 = 2/3 p1 + 1/3 p0
r2 = 2/3 p1 + 1/3 p2
and of course r0 = p0, r3 = p2
*/
int contour, point = 0, first_pt;
FT_Outline *outline = &ft_face->glyph->outline;
TTPOLYGONHEADER *pph;
TTPOLYCURVE *ppc;
DWORD pph_start, cpfx, type;
FT_Vector cubic_control[4];
if(buflen == 0) buf = NULL;
for(contour = 0; contour < outline->n_contours; contour++) {
pph_start = needed;
pph = buf + needed;
first_pt = point;
if(buf) {
pph->dwType = TT_POLYGON_TYPE;
FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
}
needed += sizeof(*pph);
point++;
while(point <= outline->contours[contour]) {
ppc = buf + needed;
type = (outline->tags[point] & FT_Curve_Tag_On) ?
TT_PRIM_LINE : TT_PRIM_CSPLINE;
cpfx = 0;
do {
if(type == TT_PRIM_LINE) {
if(buf)
FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
cpfx++;
point++;
} else {
/* Unlike QSPLINEs, CSPLINEs always have their endpoint
so cpfx = 3n */
/* FIXME: Possible optimization in endpoint calculation
if there are two consecutive curves */
cubic_control[0] = outline->points[point-1];
if(!(outline->tags[point-1] & FT_Curve_Tag_On)) {
cubic_control[0].x += outline->points[point].x + 1;
cubic_control[0].y += outline->points[point].y + 1;
cubic_control[0].x >>= 1;
cubic_control[0].y >>= 1;
}
if(point+1 > outline->contours[contour])
cubic_control[3] = outline->points[first_pt];
else {
cubic_control[3] = outline->points[point+1];
if(!(outline->tags[point+1] & FT_Curve_Tag_On)) {
cubic_control[3].x += outline->points[point].x + 1;
cubic_control[3].y += outline->points[point].y + 1;
cubic_control[3].x >>= 1;
cubic_control[3].y >>= 1;
}
}
/* r1 = 1/3 p0 + 2/3 p1
r2 = 1/3 p2 + 2/3 p1 */
cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
cubic_control[2] = cubic_control[1];
cubic_control[1].x += (cubic_control[0].x + 1) / 3;
cubic_control[1].y += (cubic_control[0].y + 1) / 3;
cubic_control[2].x += (cubic_control[3].x + 1) / 3;
cubic_control[2].y += (cubic_control[3].y + 1) / 3;
if(buf) {
FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
}
cpfx += 3;
point++;
}
} while(point <= outline->contours[contour] &&
(outline->tags[point] & FT_Curve_Tag_On) ==
(outline->tags[point-1] & FT_Curve_Tag_On));
/* At the end of a contour Windows adds the start point,
but only for Beziers and we've already done that.
*/
if(point <= outline->contours[contour] &&
outline->tags[point] & FT_Curve_Tag_On) {
/* This is the closing pt of a bezier, but we've already
added it, so just inc point and carry on */
point++;
}
if(buf) {
ppc->wType = type;
ppc->cpfx = cpfx;
}
needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
}
if(buf)
pph->cb = needed - pph_start;
}
break;
}
default: default:
FIXME("Unsupported format %d\n", format); FIXME("Unsupported format %d\n", format);
return GDI_ERROR; return GDI_ERROR;
...@@ -1424,110 +1734,16 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, ...@@ -1424,110 +1734,16 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format,
*/ */
BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm)
{ {
FT_Face ft_face = font->ft_face; if(!font->potm) {
TT_OS2 *pOS2; if(!WineEngGetOutlineTextMetrics(font, 0, NULL))
TT_HoriHeader *pHori; return FALSE;
FT_Fixed x_scale, y_scale;
TRACE("font=%p, ptm=%p\n", font, ptm);
x_scale = ft_face->size->metrics.x_scale;
y_scale = ft_face->size->metrics.y_scale;
pOS2 = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_os2);
if(!pOS2) {
FIXME("Can't find OS/2 table - not TT font?\n");
return 0;
}
pHori = pFT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea);
if(!pHori) {
FIXME("Can't find HHEA table - not TT font?\n");
return 0;
}
TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
pOS2->usWinAscent, pOS2->usWinDescent,
pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
ft_face->ascender, ft_face->descender, ft_face->height,
pHori->Ascender, pHori->Descender, pHori->Line_Gap,
ft_face->bbox.yMax, ft_face->bbox.yMin);
if(font->yMax) {
ptm->tmAscent = font->yMax;
ptm->tmDescent = -font->yMin;
ptm->tmInternalLeading = (ptm->tmAscent + ptm->tmDescent) - ft_face->size->metrics.y_ppem;
} else {
ptm->tmAscent = (pFT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6;
ptm->tmDescent = (pFT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6;
ptm->tmInternalLeading = (pFT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent
- ft_face->units_per_EM, y_scale) + 32) >> 6;
}
ptm->tmHeight = ptm->tmAscent + ptm->tmDescent;
/* MSDN says:
el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
*/
ptm->tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
((pOS2->usWinAscent + pOS2->usWinDescent) -
(pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
ptm->tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
ptm->tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
ptm->tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
ptm->tmOverhang = 0;
ptm->tmDigitizedAspectX = 300;
ptm->tmDigitizedAspectY = 300;
ptm->tmFirstChar = pOS2->usFirstCharIndex;
ptm->tmLastChar = pOS2->usLastCharIndex;
ptm->tmDefaultChar = pOS2->usDefaultChar;
ptm->tmBreakChar = pOS2->usBreakChar;
ptm->tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
ptm->tmUnderlined = 0; /* entry in OS2 table */
ptm->tmStruckOut = 0; /* entry in OS2 table */
/* Yes TPMF_FIXED_PITCH is correct; braindead api */
if(!FT_IS_FIXED_WIDTH(ft_face))
ptm->tmPitchAndFamily = TMPF_FIXED_PITCH;
else
ptm->tmPitchAndFamily = 0;
switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
case PAN_FAMILY_SCRIPT:
ptm->tmPitchAndFamily |= FF_SCRIPT;
break;
case PAN_FAMILY_DECORATIVE:
case PAN_FAMILY_PICTORIAL:
ptm->tmPitchAndFamily |= FF_DECORATIVE;
break;
case PAN_FAMILY_TEXT_DISPLAY:
if(ptm->tmPitchAndFamily == 0) /* fixed */
ptm->tmPitchAndFamily = FF_MODERN;
else {
switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
case PAN_SERIF_NORMAL_SANS:
case PAN_SERIF_OBTUSE_SANS:
case PAN_SERIF_PERP_SANS:
ptm->tmPitchAndFamily |= FF_SWISS;
break;
default:
ptm->tmPitchAndFamily |= FF_ROMAN;
}
}
break;
default:
ptm->tmPitchAndFamily |= FF_DONTCARE;
} }
if(!font->potm) return FALSE;
if(FT_IS_SCALABLE(ft_face)) memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm));
ptm->tmPitchAndFamily |= TMPF_VECTOR;
if(FT_IS_SFNT(ft_face))
ptm->tmPitchAndFamily |= TMPF_TRUETYPE;
ptm->tmCharSet = font->charset;
return TRUE; return TRUE;
} }
/************************************************************* /*************************************************************
* WineEngGetOutlineTextMetrics * WineEngGetOutlineTextMetrics
* *
...@@ -1546,6 +1762,12 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, ...@@ -1546,6 +1762,12 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
TRACE("font=%p\n", font); TRACE("font=%p\n", font);
if(font->potm) {
if(cbSize >= font->potm->otmSize)
memcpy(potm, font->potm, font->potm->otmSize);
return font->potm->otmSize;
}
needed = sizeof(*potm); needed = sizeof(*potm);
lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0) lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0)
...@@ -1578,10 +1800,6 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, ...@@ -1578,10 +1800,6 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
/* length of otmpFullName */ /* length of otmpFullName */
needed += lenfam + lensty; needed += lenfam + lensty;
if(needed > cbSize) {
ret = needed;
goto end;
}
x_scale = ft_face->size->metrics.x_scale; x_scale = ft_face->size->metrics.x_scale;
y_scale = ft_face->size->metrics.y_scale; y_scale = ft_face->size->metrics.y_scale;
...@@ -1600,53 +1818,136 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, ...@@ -1600,53 +1818,136 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
goto end; goto end;
} }
potm->otmSize = needed; TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n",
pOS2->usWinAscent, pOS2->usWinDescent,
WineEngGetTextMetrics(font, &potm->otmTextMetrics); pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap,
ft_face->ascender, ft_face->descender, ft_face->height,
potm->otmFiller = 0; pHori->Ascender, pHori->Descender, pHori->Line_Gap,
memcpy(&potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT); ft_face->bbox.yMax, ft_face->bbox.yMin);
potm->otmfsSelection = pOS2->fsSelection;
potm->otmfsType = pOS2->fsType; font->potm = HeapAlloc(GetProcessHeap(), 0, needed);
potm->otmsCharSlopeRise = pHori->caret_Slope_Rise; font->potm->otmSize = needed;
potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
potm->otmItalicAngle = 0; /* POST table */ #define TM font->potm->otmTextMetrics
potm->otmEMSquare = ft_face->units_per_EM;
potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6; if(font->yMax) {
potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6; TM.tmAscent = font->yMax;
potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6; TM.tmDescent = -font->yMin;
potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6; TM.tmInternalLeading = (TM.tmAscent + TM.tmDescent) - ft_face->size->metrics.y_ppem;
potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6; } else {
potm->otmrcFontBox.left = ft_face->bbox.xMin; TM.tmAscent = (pFT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6;
potm->otmrcFontBox.right = ft_face->bbox.xMax; TM.tmDescent = (pFT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6;
potm->otmrcFontBox.top = ft_face->bbox.yMin; TM.tmInternalLeading = (pFT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent
potm->otmrcFontBox.bottom = ft_face->bbox.yMax; - ft_face->units_per_EM, y_scale) + 32) >> 6;
potm->otmMacAscent = 0; /* where do these come from ? */ }
potm->otmMacDescent = 0;
potm->otmMacLineGap = 0; TM.tmHeight = TM.tmAscent + TM.tmDescent;
potm->otmusMinimumPPEM = 0; /* TT Header */
potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6; /* MSDN says:
potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6; el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6; */
potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6; TM.tmExternalLeading = max(0, (pFT_MulFix(pHori->Line_Gap -
potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6; ((pOS2->usWinAscent + pOS2->usWinDescent) -
potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6; (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6);
potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6; TM.tmAveCharWidth = (pFT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6;
potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6; TM.tmMaxCharWidth = (pFT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6;
potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6; TM.tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass;
potm->otmsUnderscoreSize = 0; /* POST Header */ TM.tmOverhang = 0;
potm->otmsUnderscorePosition = 0; /* POST Header */ TM.tmDigitizedAspectX = 300;
TM.tmDigitizedAspectY = 300;
TM.tmFirstChar = pOS2->usFirstCharIndex;
TM.tmLastChar = pOS2->usLastCharIndex;
TM.tmDefaultChar = pOS2->usDefaultChar;
TM.tmBreakChar = pOS2->usBreakChar ? pOS2->usBreakChar : ' ';
TM.tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0);
TM.tmUnderlined = 0; /* entry in OS2 table */
TM.tmStruckOut = 0; /* entry in OS2 table */
/* Yes TPMF_FIXED_PITCH is correct; braindead api */
if(!FT_IS_FIXED_WIDTH(ft_face))
TM.tmPitchAndFamily = TMPF_FIXED_PITCH;
else
TM.tmPitchAndFamily = 0;
switch(pOS2->panose[PAN_FAMILYTYPE_INDEX]) {
case PAN_FAMILY_SCRIPT:
TM.tmPitchAndFamily |= FF_SCRIPT;
break;
case PAN_FAMILY_DECORATIVE:
case PAN_FAMILY_PICTORIAL:
TM.tmPitchAndFamily |= FF_DECORATIVE;
break;
case PAN_FAMILY_TEXT_DISPLAY:
if(TM.tmPitchAndFamily == 0) /* fixed */
TM.tmPitchAndFamily = FF_MODERN;
else {
switch(pOS2->panose[PAN_SERIFSTYLE_INDEX]) {
case PAN_SERIF_NORMAL_SANS:
case PAN_SERIF_OBTUSE_SANS:
case PAN_SERIF_PERP_SANS:
TM.tmPitchAndFamily |= FF_SWISS;
break;
default:
TM.tmPitchAndFamily |= FF_ROMAN;
}
}
break;
default:
TM.tmPitchAndFamily |= FF_DONTCARE;
}
if(FT_IS_SCALABLE(ft_face))
TM.tmPitchAndFamily |= TMPF_VECTOR;
if(FT_IS_SFNT(ft_face))
TM.tmPitchAndFamily |= TMPF_TRUETYPE;
TM.tmCharSet = font->charset;
#undef TM
font->potm->otmFiller = 0;
memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT);
font->potm->otmfsSelection = pOS2->fsSelection;
font->potm->otmfsType = pOS2->fsType;
font->potm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
font->potm->otmsCharSlopeRun = pHori->caret_Slope_Run;
font->potm->otmItalicAngle = 0; /* POST table */
font->potm->otmEMSquare = ft_face->units_per_EM;
font->potm->otmAscent = (pFT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6;
font->potm->otmDescent = (pFT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6;
font->potm->otmLineGap = (pFT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6;
font->potm->otmsCapEmHeight = (pFT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6;
font->potm->otmsXHeight = (pFT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6;
font->potm->otmrcFontBox.left = ft_face->bbox.xMin;
font->potm->otmrcFontBox.right = ft_face->bbox.xMax;
font->potm->otmrcFontBox.top = ft_face->bbox.yMin;
font->potm->otmrcFontBox.bottom = ft_face->bbox.yMax;
font->potm->otmMacAscent = 0; /* where do these come from ? */
font->potm->otmMacDescent = 0;
font->potm->otmMacLineGap = 0;
font->potm->otmusMinimumPPEM = 0; /* TT Header */
font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6;
font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6;
font->potm->otmptSubscriptOffset.x = (pFT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6;
font->potm->otmptSubscriptOffset.y = (pFT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6;
font->potm->otmptSuperscriptSize.x = (pFT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6;
font->potm->otmptSuperscriptSize.y = (pFT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6;
font->potm->otmptSuperscriptOffset.x = (pFT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6;
font->potm->otmptSuperscriptOffset.y = (pFT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6;
font->potm->otmsStrikeoutSize = (pFT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6;
font->potm->otmsStrikeoutPosition = (pFT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6;
font->potm->otmsUnderscoreSize = 0; /* POST Header */
font->potm->otmsUnderscorePosition = 0; /* POST Header */
/* otmp* members should clearly have type ptrdiff_t, but M$ knows best */ /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */
cp = (char*)potm + sizeof(*potm); cp = (char*)font->potm + sizeof(*font->potm);
potm->otmpFamilyName = (LPSTR)(cp - (char*)potm); font->potm->otmpFamilyName = (LPSTR)(cp - (char*)font->potm);
strcpyW((WCHAR*)cp, family_nameW); strcpyW((WCHAR*)cp, family_nameW);
cp += lenfam; cp += lenfam;
potm->otmpStyleName = (LPSTR)(cp - (char*)potm); font->potm->otmpStyleName = (LPSTR)(cp - (char*)font->potm);
strcpyW((WCHAR*)cp, style_nameW); strcpyW((WCHAR*)cp, style_nameW);
cp += lensty; cp += lensty;
potm->otmpFaceName = (LPSTR)(cp - (char*)potm); font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm);
strcpyW((WCHAR*)cp, family_nameW); strcpyW((WCHAR*)cp, family_nameW);
if(strcasecmp(ft_face->style_name, "regular")) { if(strcasecmp(ft_face->style_name, "regular")) {
strcatW((WCHAR*)cp, spaceW); strcatW((WCHAR*)cp, spaceW);
...@@ -1654,13 +1955,16 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, ...@@ -1654,13 +1955,16 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize,
cp += lenfam + lensty; cp += lenfam + lensty;
} else } else
cp += lenfam; cp += lenfam;
potm->otmpFullName = (LPSTR)(cp - (char*)potm); font->potm->otmpFullName = (LPSTR)(cp - (char*)font->potm);
strcpyW((WCHAR*)cp, family_nameW); strcpyW((WCHAR*)cp, family_nameW);
strcatW((WCHAR*)cp, spaceW); strcatW((WCHAR*)cp, spaceW);
strcatW((WCHAR*)cp, style_nameW); strcatW((WCHAR*)cp, style_nameW);
ret = needed; ret = needed;
end: if(needed <= cbSize)
memcpy(potm, font->potm, font->potm->otmSize);
end:
HeapFree(GetProcessHeap(), 0, style_nameW); HeapFree(GetProcessHeap(), 0, style_nameW);
HeapFree(GetProcessHeap(), 0, family_nameW); HeapFree(GetProcessHeap(), 0, family_nameW);
...@@ -1785,6 +2089,20 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf, ...@@ -1785,6 +2089,20 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
return len; return len;
} }
/*************************************************************
* WineEngGetTextFace
*
*/
INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
{
if(str) {
lstrcpynW(str, font->name, count);
return strlenW(font->name);
} else
return strlenW(font->name) + 1;
}
#else /* HAVE_FREETYPE */ #else /* HAVE_FREETYPE */
BOOL WineEngInit(void) BOOL WineEngInit(void)
...@@ -1859,4 +2177,22 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf, ...@@ -1859,4 +2177,22 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf,
ERR("called but we don't have FreeType\n"); ERR("called but we don't have FreeType\n");
return GDI_ERROR; return GDI_ERROR;
} }
INT WineEngGetTextFace(GdiFont font, INT count, LPWSTR str)
{
ERR("called but we don't have FreeType\n");
return 0;
}
INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
{
FIXME(":stub\n");
return 1;
}
INT WineEngRemoveFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
{
FIXME(":stub\n");
return TRUE;
}
#endif /* HAVE_FREETYPE */ #endif /* HAVE_FREETYPE */
...@@ -10,6 +10,8 @@ init MAIN_GdiInit ...@@ -10,6 +10,8 @@ init MAIN_GdiInit
@ stdcall AbortDoc(long) AbortDoc @ stdcall AbortDoc(long) AbortDoc
@ stdcall AbortPath(long) AbortPath @ stdcall AbortPath(long) AbortPath
@ stdcall AddFontResourceA(str) AddFontResourceA @ stdcall AddFontResourceA(str) AddFontResourceA
@ stdcall AddFontResourceExA(str long ptr) AddFontResourceExA
@ stdcall AddFontResourceExW(wstr long ptr) AddFontResourceExW
@ stub AddFontResourceTracking @ stub AddFontResourceTracking
@ stdcall AddFontResourceW(wstr) AddFontResourceW @ stdcall AddFontResourceW(wstr) AddFontResourceW
@ stdcall AngleArc(long long long long long long) AngleArc @ stdcall AngleArc(long long long long long long) AngleArc
...@@ -319,6 +321,8 @@ init MAIN_GdiInit ...@@ -319,6 +321,8 @@ init MAIN_GdiInit
@ stdcall RectVisible(long ptr) RectVisible @ stdcall RectVisible(long ptr) RectVisible
@ stdcall Rectangle(long long long long long) Rectangle @ stdcall Rectangle(long long long long long) Rectangle
@ stdcall RemoveFontResourceA(str) RemoveFontResourceA @ stdcall RemoveFontResourceA(str) RemoveFontResourceA
@ stdcall RemoveFontResourceExA(str long ptr) RemoveFontResourceExA
@ stdcall RemoveFontResourceExW(wstr long ptr) RemoveFontResourceExW
@ stub RemoveFontResourceTracking @ stub RemoveFontResourceTracking
@ stdcall RemoveFontResourceW(wstr) RemoveFontResourceW @ stdcall RemoveFontResourceW(wstr) RemoveFontResourceW
@ stdcall ResetDCA(long ptr) ResetDCA @ stdcall ResetDCA(long ptr) ResetDCA
......
...@@ -38,6 +38,7 @@ extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW); ...@@ -38,6 +38,7 @@ extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW);
extern LPWSTR FONT_mbtowc(HDC, LPCSTR, INT, INT*, UINT*); extern LPWSTR FONT_mbtowc(HDC, LPCSTR, INT, INT*, UINT*);
extern INT WineEngAddFontResourceEx(LPCWSTR, DWORD, PVOID);
extern GdiFont WineEngCreateFontInstance(DC*, HFONT); extern GdiFont WineEngCreateFontInstance(DC*, HFONT);
extern BOOL WineEngDestroyFontInstance(HFONT handle); extern BOOL WineEngDestroyFontInstance(HFONT handle);
extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM); extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM);
...@@ -51,7 +52,9 @@ extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format, ...@@ -51,7 +52,9 @@ extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format,
extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW); extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW);
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 BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW); extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW);
extern BOOL WineEngInit(void); extern BOOL WineEngInit(void);
extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID);
#endif /* __WINE_FONT_H */ #endif /* __WINE_FONT_H */
...@@ -684,6 +684,7 @@ typedef struct ...@@ -684,6 +684,7 @@ typedef struct
#define HEBREW_CHARSET (BYTE)177 /* CP1255, -iso8859-8 */ #define HEBREW_CHARSET (BYTE)177 /* CP1255, -iso8859-8 */
#define ARABIC_CHARSET (BYTE)178 /* CP1256, -iso8859-6 */ #define ARABIC_CHARSET (BYTE)178 /* CP1256, -iso8859-6 */
#define BALTIC_CHARSET (BYTE)186 /* CP1257, -iso8859-13 */ #define BALTIC_CHARSET (BYTE)186 /* CP1257, -iso8859-13 */
#define VIETNAMESE_CHARSET (BYTE)163 /* CP1258 */
#define RUSSIAN_CHARSET (BYTE)204 /* CP1251, -iso8859-5 */ #define RUSSIAN_CHARSET (BYTE)204 /* CP1251, -iso8859-5 */
#define EE_CHARSET (BYTE)238 /* CP1250, -iso8859-2 */ #define EE_CHARSET (BYTE)238 /* CP1250, -iso8859-2 */
#define EASTEUROPE_CHARSET EE_CHARSET #define EASTEUROPE_CHARSET EE_CHARSET
...@@ -1235,6 +1236,7 @@ typedef struct ...@@ -1235,6 +1236,7 @@ typedef struct
#define GGO_METRICS 0 #define GGO_METRICS 0
#define GGO_BITMAP 1 #define GGO_BITMAP 1
#define GGO_NATIVE 2 #define GGO_NATIVE 2
#define GGO_BEZIER 3
#define GGO_GRAY2_BITMAP 4 #define GGO_GRAY2_BITMAP 4
#define GGO_GRAY4_BITMAP 5 #define GGO_GRAY4_BITMAP 5
#define GGO_GRAY8_BITMAP 6 #define GGO_GRAY8_BITMAP 6
...@@ -1365,6 +1367,7 @@ typedef struct ...@@ -1365,6 +1367,7 @@ typedef struct
#define TT_PRIM_LINE 1 #define TT_PRIM_LINE 1
#define TT_PRIM_QSPLINE 2 #define TT_PRIM_QSPLINE 2
#define TT_PRIM_CSPLINE 3
#define TT_POLYGON_TYPE 24 #define TT_POLYGON_TYPE 24
/* Get/SetSystemPaletteUse() values */ /* Get/SetSystemPaletteUse() values */
...@@ -3046,11 +3049,19 @@ typedef struct _BLENDFUNCTION ...@@ -3046,11 +3049,19 @@ typedef struct _BLENDFUNCTION
#define GDI_ERROR (0xFFFFFFFFL) #define GDI_ERROR (0xFFFFFFFFL)
#define HGDI_ERROR ((HANDLE)0xFFFFFFFFL) #define HGDI_ERROR ((HANDLE)0xFFFFFFFFL)
/* AddFontResourceEx flags */
#define FR_PRIVATE 0x10
#define FR_NOT_ENUM 0x20
INT WINAPI AbortDoc(HDC); INT WINAPI AbortDoc(HDC);
BOOL WINAPI AbortPath(HDC); BOOL WINAPI AbortPath(HDC);
INT WINAPI AddFontResourceA(LPCSTR); INT WINAPI AddFontResourceA(LPCSTR);
INT WINAPI AddFontResourceW(LPCWSTR); INT WINAPI AddFontResourceW(LPCWSTR);
#define AddFontResource WINELIB_NAME_AW(AddFontResource) #define AddFontResource WINELIB_NAME_AW(AddFontResource)
INT WINAPI AddFontResourceExA(LPCSTR, DWORD, PVOID);
INT WINAPI AddFontResourceExW(LPCWSTR, DWORD, PVOID);
#define AddFontResourceEx WINELIB_NAME_AW(AddFontResourceEx)
BOOL WINAPI AlphaBlend(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION); BOOL WINAPI AlphaBlend(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION);
BOOL WINAPI AngleArc(HDC, INT, INT, DWORD, FLOAT, FLOAT); BOOL WINAPI AngleArc(HDC, INT, INT, DWORD, FLOAT, FLOAT);
BOOL WINAPI AnimatePalette(HPALETTE,UINT,UINT,const PALETTEENTRY*); BOOL WINAPI AnimatePalette(HPALETTE,UINT,UINT,const PALETTEENTRY*);
...@@ -3331,6 +3342,9 @@ BOOL WINAPI RectVisible(HDC,const RECT*); ...@@ -3331,6 +3342,9 @@ BOOL WINAPI RectVisible(HDC,const RECT*);
BOOL WINAPI RemoveFontResourceA(LPCSTR); BOOL WINAPI RemoveFontResourceA(LPCSTR);
BOOL WINAPI RemoveFontResourceW(LPCWSTR); BOOL WINAPI RemoveFontResourceW(LPCWSTR);
#define RemoveFontResource WINELIB_NAME_AW(RemoveFontResource) #define RemoveFontResource WINELIB_NAME_AW(RemoveFontResource)
BOOL WINAPI RemoveFontResourceExA(LPCSTR, DWORD, PVOID);
BOOL WINAPI RemoveFontResourceExW(LPCWSTR, DWORD, PVOID);
#define RemoveFontResourceEx WINELIB_NAME_AW(RemoveFontResourceEx)
HDC WINAPI ResetDCA(HDC,const DEVMODEA *); HDC WINAPI ResetDCA(HDC,const DEVMODEA *);
HDC WINAPI ResetDCW(HDC,const DEVMODEW *); HDC WINAPI ResetDCW(HDC,const DEVMODEW *);
#define ResetDC WINELIB_NAME_AW(ResetDC) #define ResetDC WINELIB_NAME_AW(ResetDC)
......
...@@ -98,6 +98,7 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = { ...@@ -98,6 +98,7 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
{ HEBREW_CHARSET, 1255, FS(5)}, { HEBREW_CHARSET, 1255, FS(5)},
{ ARABIC_CHARSET, 1256, FS(6)}, { ARABIC_CHARSET, 1256, FS(6)},
{ BALTIC_CHARSET, 1257, FS(7)}, { BALTIC_CHARSET, 1257, FS(7)},
{ VIETNAMESE_CHARSET, 1258, FS(8)},
/* reserved by ANSI */ /* reserved by ANSI */
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
...@@ -106,7 +107,6 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = { ...@@ -106,7 +107,6 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)},
/* ANSI and OEM */ /* ANSI and OEM */
{ THAI_CHARSET, 874, FS(16)}, { THAI_CHARSET, 874, FS(16)},
{ SHIFTJIS_CHARSET, 932, FS(17)}, { SHIFTJIS_CHARSET, 932, FS(17)},
...@@ -125,7 +125,7 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = { ...@@ -125,7 +125,7 @@ static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
/* reserved for system */ /* reserved for system */
{ DEFAULT_CHARSET, 0, FS(0)}, { DEFAULT_CHARSET, 0, FS(0)},
{ DEFAULT_CHARSET, 0, FS(0)}, { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
}; };
/* ### start build ### */ /* ### start build ### */
...@@ -1104,7 +1104,9 @@ INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name ) ...@@ -1104,7 +1104,9 @@ INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
DC * dc = DC_GetDCPtr( hdc ); DC * dc = DC_GetDCPtr( hdc );
if (!dc) return 0; if (!dc) return 0;
if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC ))) if(dc->gdiFont)
ret = WineEngGetTextFace(dc->gdiFont, count, name);
else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
{ {
if (name) if (name)
{ {
...@@ -1393,11 +1395,11 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics ) ...@@ -1393,11 +1395,11 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
* therefore we have to convert them to logical */ * therefore we have to convert them to logical */
#define WDPTOLP(x) ((x<0)? \ #define WDPTOLP(x) ((x<0)? \
(-abs((x)*dc->wndExtX/dc->vportExtX)): \ (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
(abs((x)*dc->wndExtX/dc->vportExtX))) (abs(INTERNAL_XDSTOWS(dc, (x)))))
#define HDPTOLP(y) ((y<0)? \ #define HDPTOLP(y) ((y<0)? \
(-abs((y)*dc->wndExtY/dc->vportExtY)): \ (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
(abs((y)*dc->wndExtY/dc->vportExtY))) (abs(INTERNAL_YDSTOWS(dc, (y)))))
metrics->tmHeight = HDPTOLP(metrics->tmHeight); metrics->tmHeight = HDPTOLP(metrics->tmHeight);
metrics->tmAscent = HDPTOLP(metrics->tmAscent); metrics->tmAscent = HDPTOLP(metrics->tmAscent);
...@@ -2242,7 +2244,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount, ...@@ -2242,7 +2244,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
DWORD dwFlags) DWORD dwFlags)
{ {
WCHAR *lpStringW; WCHAR *lpStringW;
INT uCountW; INT uCountW, i;
GCP_RESULTSW resultsW; GCP_RESULTSW resultsW;
DWORD ret; DWORD ret;
UINT font_cp; UINT font_cp;
...@@ -2261,9 +2263,14 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount, ...@@ -2261,9 +2263,14 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags); ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
if(lpResults->lpOutString) if(lpResults->lpOutString) {
WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW, if(font_cp != CP_SYMBOL)
lpResults->lpOutString, uCount, NULL, NULL ); WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
lpResults->lpOutString, uCount, NULL, NULL );
else
for(i = 0; i < uCount; i++)
lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
}
HeapFree(GetProcessHeap(), 0, lpStringW); HeapFree(GetProcessHeap(), 0, lpStringW);
HeapFree(GetProcessHeap(), 0, resultsW.lpOutString); HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
...@@ -2482,38 +2489,50 @@ BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar, ...@@ -2482,38 +2489,50 @@ BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
* *
* Can be either .FON, or .FNT, or .TTF, or .FOT font file. * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
* *
* FIXME: Load header and find the best-matching font in the fontList;
* fixup dfPoints if all metrics are identical, otherwise create
* new fontAlias. When soft font support is ready this will
* simply create a new fontResource ('filename' will go into
* the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
* flag set.
*/ */
INT16 WINAPI AddFontResource16( LPCSTR filename ) INT16 WINAPI AddFontResource16( LPCSTR filename )
{ {
return AddFontResourceA( filename ); return AddFontResourceA( filename );
} }
/*********************************************************************** /***********************************************************************
* AddFontResourceA (GDI32.@) * AddFontResourceA (GDI32.@)
*/ */
INT WINAPI AddFontResourceA( LPCSTR str ) INT WINAPI AddFontResourceA( LPCSTR str )
{ {
FIXME("(%s): stub! Read the Wine User Guide on how to install " return AddFontResourceExA( str, 0, NULL);
"this font manually.\n", debugstr_a(str));
return 1;
} }
/*********************************************************************** /***********************************************************************
* AddFontResourceW (GDI32.@) * AddFontResourceW (GDI32.@)
*/ */
INT WINAPI AddFontResourceW( LPCWSTR str ) INT WINAPI AddFontResourceW( LPCWSTR str )
{ {
FIXME("(%s): stub! Read the Wine User Guide on how to install " return AddFontResourceExW(str, 0, NULL);
"this font manually.\n", debugstr_w(str)); }
return 1;
/***********************************************************************
* AddFontResourceExA (GDI32.@)
*/
INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
{
DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
INT ret;
MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
ret = AddFontResourceExW(strW, fl, pdv);
HeapFree(GetProcessHeap(), 0, strW);
return ret;
}
/***********************************************************************
* AddFontResourceExW (GDI32.@)
*/
INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
{
return WineEngAddFontResourceEx(str, fl, pdv);
} }
/*********************************************************************** /***********************************************************************
...@@ -2521,48 +2540,44 @@ INT WINAPI AddFontResourceW( LPCWSTR str ) ...@@ -2521,48 +2540,44 @@ INT WINAPI AddFontResourceW( LPCWSTR str )
*/ */
BOOL16 WINAPI RemoveFontResource16( LPCSTR str ) BOOL16 WINAPI RemoveFontResource16( LPCSTR str )
{ {
FIXME("(%s): stub\n", debugstr_a(str)); return RemoveFontResourceA(str);
return TRUE;
} }
/*********************************************************************** /***********************************************************************
* RemoveFontResourceA (GDI32.@) * RemoveFontResourceA (GDI32.@)
*/ */
BOOL WINAPI RemoveFontResourceA( LPCSTR str ) BOOL WINAPI RemoveFontResourceA( LPCSTR str )
{ {
/* This is how it should look like */ return RemoveFontResourceExA(str, 0, 0);
/*
fontResource** ppfr;
BOOL32 retVal = FALSE;
EnterCriticalSection( &crtsc_fonts_X11 );
for( ppfr = &fontList; *ppfr; ppfr = &(*ppfr)->next )
if( !strcasecmp( (*ppfr)->lfFaceName, str ) )
{
if(((*ppfr)->fr_flags & (FR_SOFTFONT | FR_SOFTRESOURCE)) &&
(*ppfr)->hOwnerProcess == GetCurrentProcess() )
{
if( (*ppfr)->fo_count )
(*ppfr)->fr_flags |= FR_REMOVED;
else
XFONT_RemoveFontResource( ppfr );
}
retVal = TRUE;
}
LeaveCriticalSection( &crtsc_fonts_X11 );
return retVal;
*/
FIXME("(%s): stub\n", debugstr_a(str));
return TRUE;
} }
/*********************************************************************** /***********************************************************************
* RemoveFontResourceW (GDI32.@) * RemoveFontResourceW (GDI32.@)
*/ */
BOOL WINAPI RemoveFontResourceW( LPCWSTR str ) BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
{ {
FIXME("(%s): stub\n", debugstr_w(str) ); return RemoveFontResourceExW(str, 0, 0);
return TRUE; }
/***********************************************************************
* RemoveFontResourceExA (GDI32.@)
*/
BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
{
DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
INT ret;
MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
ret = RemoveFontResourceExW(strW, fl, pdv);
HeapFree(GetProcessHeap(), 0, strW);
return ret;
}
/***********************************************************************
* RemoveFontResourceExW (GDI32.@)
*/
BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
{
return WineEngRemoveFontResourceEx(str, fl, pdv);
} }
...@@ -40,13 +40,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(text); ...@@ -40,13 +40,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(text);
* number of bytes to convert. If plenW is non-NULL, on return it * number of bytes to convert. If plenW is non-NULL, on return it
* will point to the number of WCHARs (excluding the '\0') that have * will point to the number of WCHARs (excluding the '\0') that have
* been written. If pCP is non-NULL, on return it will point to the * been written. If pCP is non-NULL, on return it will point to the
* codepage used in the conversion. The caller should free the * codepage used in the conversion (NB, this may be CP_SYMBOL so watch
* returned LPWSTR from the process heap itself. * out). The caller should free the returned LPWSTR from the process
* heap itself.
*/ */
LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP) LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
{ {
UINT cp = CP_ACP; UINT cp = CP_ACP;
INT lenW; INT lenW, i;
LPWSTR strW; LPWSTR strW;
CHARSETINFO csi; CHARSETINFO csi;
int charset = GetTextCharset(hdc); int charset = GetTextCharset(hdc);
...@@ -56,9 +57,6 @@ LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP) ...@@ -56,9 +57,6 @@ LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
cp = csi.ciACP; cp = csi.ciACP;
else { else {
switch(charset) { switch(charset) {
case SYMBOL_CHARSET: /* We don't want any translation here */
cp = GetACP();
break;
case OEM_CHARSET: case OEM_CHARSET:
cp = GetOEMCP(); cp = GetOEMCP();
break; break;
...@@ -90,10 +88,20 @@ LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP) ...@@ -90,10 +88,20 @@ LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
} }
} }
lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); TRACE("cp == %d\n", cp);
strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
MultiByteToWideChar(cp, 0, str, count, strW, lenW); if(count == -1) count = strlen(str);
if(cp != CP_SYMBOL) {
lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
MultiByteToWideChar(cp, 0, str, count, strW, lenW);
} else {
lenW = count;
strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
for(i = 0; i < count; i++) strW[i] = (BYTE)str[i];
}
strW[lenW] = '\0'; strW[lenW] = '\0';
TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
if(plenW) *plenW = lenW; if(plenW) *plenW = lenW;
if(pCP) *pCP = cp; if(pCP) *pCP = cp;
return strW; return strW;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment