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:
Huw Davies 2010-02-02 10:20:50 +00:00 committed by Alexandre Julliard
parent cf602ca422
commit 7e42fd8b4e
2 changed files with 155 additions and 5 deletions

View File

@ -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);
}
}

View File

@ -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();
}