oleaut32: If the font name property is changed, don't insist on the current charset when selecting a new font.
This commit is contained in:
parent
cf602ca422
commit
7e42fd8b4e
|
@ -53,6 +53,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|||
#define FONTPERSIST_UNDERLINE 0x04
|
||||
#define FONTPERSIST_STRIKETHROUGH 0x08
|
||||
|
||||
static HDC olefont_hdc;
|
||||
|
||||
/***********************************************************************
|
||||
* List of the HFONTs it has given out, with each one having a separate
|
||||
|
@ -91,6 +92,28 @@ static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
|
|||
};
|
||||
static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static HDC get_dc(void)
|
||||
{
|
||||
HDC hdc;
|
||||
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
||||
if(!olefont_hdc)
|
||||
olefont_hdc = CreateCompatibleDC(NULL);
|
||||
hdc = olefont_hdc;
|
||||
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
||||
return hdc;
|
||||
}
|
||||
|
||||
static void delete_dc(void)
|
||||
{
|
||||
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
|
||||
if(olefont_hdc)
|
||||
{
|
||||
DeleteDC(olefont_hdc);
|
||||
olefont_hdc = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
||||
}
|
||||
|
||||
static void HFONTItem_Delete(PHFONTItem item)
|
||||
{
|
||||
DeleteObject(item->gdiFont);
|
||||
|
@ -204,6 +227,17 @@ static HRESULT dec_ext_ref(HFONT hfont)
|
|||
return hr;
|
||||
}
|
||||
|
||||
static WCHAR *strdupW(const WCHAR* str)
|
||||
{
|
||||
WCHAR *ret;
|
||||
DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
|
||||
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if(ret)
|
||||
memcpy(ret, str, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Declaration of the implementation class for the IFont interface
|
||||
*/
|
||||
|
@ -531,6 +565,7 @@ static ULONG WINAPI OLEFontImpl_Release(
|
|||
LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
|
||||
HFONTItem_Delete(item);
|
||||
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
|
||||
delete_dc();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -542,31 +577,77 @@ static ULONG WINAPI OLEFontImpl_Release(
|
|||
return ret;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short orig_cs;
|
||||
short avail_cs;
|
||||
} enum_data;
|
||||
|
||||
static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
|
||||
{
|
||||
enum_data *data = (enum_data*)lp;
|
||||
|
||||
if(elf->lfCharSet == data->orig_cs)
|
||||
{
|
||||
data->avail_cs = data->orig_cs;
|
||||
return 0;
|
||||
}
|
||||
if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void realize_font(OLEFontImpl *This)
|
||||
{
|
||||
if (This->dirty)
|
||||
{
|
||||
LOGFONTW logFont;
|
||||
INT fontHeight;
|
||||
WCHAR text_face[LF_FACESIZE];
|
||||
HDC hdc = get_dc();
|
||||
HFONT old_font;
|
||||
TEXTMETRICW tm;
|
||||
|
||||
text_face[0] = 0;
|
||||
|
||||
if(This->gdiFont)
|
||||
{
|
||||
old_font = SelectObject(hdc, This->gdiFont);
|
||||
GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
|
||||
SelectObject(hdc, old_font);
|
||||
dec_int_ref(This->gdiFont);
|
||||
This->gdiFont = 0;
|
||||
}
|
||||
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
|
||||
lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
|
||||
logFont.lfCharSet = This->description.sCharset;
|
||||
|
||||
/* If the font name has been changed then enumerate all charsets
|
||||
and pick one that'll result in the font specified being selected */
|
||||
if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
|
||||
{
|
||||
enum_data data;
|
||||
data.orig_cs = This->description.sCharset;
|
||||
data.avail_cs = -1;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
|
||||
if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The height of the font returned by the get_Size property is the
|
||||
* height of the font in points multiplied by 10000... Using some
|
||||
* simple conversions and the ratio given by the application, it can
|
||||
* be converted to a height in pixels.
|
||||
*
|
||||
* Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
|
||||
* Ratio is applied here relative to the standard.
|
||||
*/
|
||||
|
||||
/* Standard ratio is 72 / 2540, or 18 / 635 in lowest terms. */
|
||||
/* Ratio is applied here relative to the standard. */
|
||||
fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
|
||||
|
||||
memset(&logFont, 0, sizeof(LOGFONTW));
|
||||
|
||||
logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
|
||||
(-fontHeight/10000L);
|
||||
|
@ -574,17 +655,28 @@ static void realize_font(OLEFontImpl *This)
|
|||
logFont.lfUnderline = This->description.fUnderline;
|
||||
logFont.lfStrikeOut = This->description.fStrikethrough;
|
||||
logFont.lfWeight = This->description.sWeight;
|
||||
logFont.lfCharSet = This->description.sCharset;
|
||||
logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = DEFAULT_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
|
||||
|
||||
This->gdiFont = CreateFontIndirectW(&logFont);
|
||||
This->dirty = FALSE;
|
||||
|
||||
add_hfontitem(This->gdiFont);
|
||||
|
||||
/* Fixup the name and charset properties so that they match the
|
||||
selected font */
|
||||
old_font = SelectObject(get_dc(), This->gdiFont);
|
||||
GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
|
||||
if(lstrcmpiW(text_face, This->description.lpstrName))
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
|
||||
This->description.lpstrName = strdupW(text_face);
|
||||
}
|
||||
GetTextMetricsW(hdc, &tm);
|
||||
This->description.sCharset = tm.tmCharSet;
|
||||
SelectObject(hdc, old_font);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
|||
static WCHAR MSSansSerif_font[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
|
||||
static WCHAR system_font[] = { 'S','y','s','t','e','m',0 };
|
||||
static WCHAR arial_font[] = { 'A','r','i','a','l',0 };
|
||||
static WCHAR marlett_font[] = { 'M','a','r','l','e','t','t',0 };
|
||||
|
||||
static HMODULE hOleaut32;
|
||||
|
||||
|
@ -1018,6 +1019,62 @@ todo_wine
|
|||
ok(obj_type == 0, "got obj type %d\n", obj_type);
|
||||
}
|
||||
|
||||
static void test_realization(void)
|
||||
{
|
||||
IFont *font;
|
||||
FONTDESC fontdesc;
|
||||
HRESULT hr;
|
||||
BSTR name;
|
||||
SHORT cs;
|
||||
|
||||
/* Try to create a symbol only font (marlett) with charset
|
||||
set to ANSI. This will result in another, ANSI, font
|
||||
being selected */
|
||||
fontdesc.cbSizeofstruct = sizeof(fontdesc);
|
||||
fontdesc.lpstrName = marlett_font;
|
||||
fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */
|
||||
fontdesc.sWeight = FW_NORMAL;
|
||||
fontdesc.sCharset = ANSI_CHARSET;
|
||||
fontdesc.fItalic = FALSE;
|
||||
fontdesc.fUnderline = FALSE;
|
||||
fontdesc.fStrikethrough = FALSE;
|
||||
|
||||
hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font);
|
||||
ok_ole_success(hr, "OleCreateFontIndirect");
|
||||
|
||||
hr = IFont_get_Charset(font, &cs);
|
||||
ok_ole_success(hr, "get_Charset");
|
||||
ok(cs == ANSI_CHARSET, "got charset %d\n", cs);
|
||||
|
||||
IFont_Release(font);
|
||||
|
||||
/* Now create an ANSI font and change the name to marlett */
|
||||
|
||||
fontdesc.lpstrName = arial_font;
|
||||
|
||||
hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&font);
|
||||
ok_ole_success(hr, "OleCreateFontIndirect");
|
||||
|
||||
hr = IFont_get_Charset(font, &cs);
|
||||
ok_ole_success(hr, "get_Charset");
|
||||
ok(cs == ANSI_CHARSET, "got charset %d\n", cs);
|
||||
|
||||
name = SysAllocString(marlett_font);
|
||||
hr = IFont_put_Name(font, name);
|
||||
ok_ole_success(hr, "put_Name");
|
||||
SysFreeString(name);
|
||||
|
||||
hr = IFont_get_Name(font, &name);
|
||||
ok_ole_success(hr, "get_Name");
|
||||
ok(!lstrcmpiW(name, marlett_font), "got name %s\n", wine_dbgstr_w(name));
|
||||
SysFreeString(name);
|
||||
|
||||
hr = IFont_get_Charset(font, &cs);
|
||||
ok_ole_success(hr, "get_Charset");
|
||||
ok(cs == SYMBOL_CHARSET, "got charset %d\n", cs);
|
||||
|
||||
IFont_Release(font);
|
||||
}
|
||||
|
||||
START_TEST(olefont)
|
||||
{
|
||||
|
@ -1053,4 +1110,5 @@ START_TEST(olefont)
|
|||
test_AddRefHfont();
|
||||
test_returns();
|
||||
test_hfont_lifetime();
|
||||
test_realization();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue