From c22b2192e5710f6a4eacf39b88ece6186c995338 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 7 Dec 2016 16:46:39 +0300 Subject: [PATCH] dwrite: Improve ConvertFontFaceToLOGFONT using same logic IDWriteFont uses. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 18 ++ dlls/dwrite/gdiinterop.c | 55 +----- dlls/dwrite/tests/font.c | 335 +++++++++++++++++++---------------- 4 files changed, 210 insertions(+), 200 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 1e46498d900..7d1cfa8526e 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -163,7 +163,6 @@ struct fontface_desc struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */ }; -extern HRESULT convert_fontface_to_logfont(IDWriteFontFace*, LOGFONTW*) DECLSPEC_HIDDEN; extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN; extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH, FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN; @@ -201,6 +200,7 @@ extern HRESULT factory_get_cached_fontface(IDWriteFactory4*,IDWriteFontFile*cons struct list**) DECLSPEC_HIDDEN; extern void factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN; extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN; +extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN; /* Opentype font table functions */ struct dwrite_font_props { diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 17bea89c76f..ba9702500c9 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -243,6 +243,8 @@ struct dwrite_fontface { DWRITE_FONT_STRETCH stretch; DWRITE_FONT_WEIGHT weight; DWRITE_PANOSE panose; + + LOGFONTW lf; }; struct dwrite_fontfile { @@ -1685,12 +1687,26 @@ static struct dwrite_font *unsafe_impl_from_IDWriteFont(IDWriteFont *iface) return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont3_iface); } +static struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl = (IDWriteFontFaceVtbl*)&dwritefontfacevtbl); + return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace4_iface); +} + void get_logfont_from_font(IDWriteFont *iface, LOGFONTW *lf) { struct dwrite_font *font = unsafe_impl_from_IDWriteFont(iface); *lf = font->data->lf; } +void get_logfont_from_fontface(IDWriteFontFace *iface, LOGFONTW *lf) +{ + struct dwrite_fontface *fontface = unsafe_impl_from_IDWriteFontFace(iface); + *lf = fontface->lf; +} + static HRESULT create_font(struct dwrite_font_data *data, IDWriteFontFamily1 *family, IDWriteFont3 **font) { struct dwrite_font *This; @@ -4284,6 +4300,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret fontface->style = desc->font_data->style; fontface->stretch = desc->font_data->stretch; fontface->panose = desc->font_data->panose; + fontface->lf = desc->font_data->lf; } else { IDWriteLocalizedStrings *names; @@ -4299,6 +4316,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret fontface->style = data->style; fontface->stretch = data->stretch; fontface->panose = data->panose; + fontface->lf = data->lf; IDWriteLocalizedStrings_Release(names); release_font_data(data); diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c index 36758753f56..67fc4a0f68d 100644 --- a/dlls/dwrite/gdiinterop.c +++ b/dlls/dwrite/gdiinterop.c @@ -658,67 +658,20 @@ static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop1 *iface, static HRESULT WINAPI gdiinterop_ConvertFontFaceToLOGFONT(IDWriteGdiInterop1 *iface, IDWriteFontFace *fontface, LOGFONTW *logfont) { - static const WCHAR enusW[] = {'e','n','-','u','s',0}; struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface); - IDWriteLocalizedStrings *familynames; - DWRITE_FONT_SIMULATIONS simulations; - struct file_stream_desc stream_desc; - struct dwrite_font_props props; - IDWriteFontFileStream *stream; - IDWriteFontFile *file = NULL; - UINT32 index; - BOOL exists; - HRESULT hr; TRACE("(%p)->(%p %p)\n", This, fontface, logfont); memset(logfont, 0, sizeof(*logfont)); - index = 1; - hr = IDWriteFontFace_GetFiles(fontface, &index, &file); - if (FAILED(hr) || !file) - return hr; - - hr = get_filestream_from_file(file, &stream); - if (FAILED(hr)) { - IDWriteFontFile_Release(file); - return hr; - } - - stream_desc.stream = stream; - stream_desc.face_type = IDWriteFontFace_GetType(fontface); - stream_desc.face_index = IDWriteFontFace_GetIndex(fontface); - opentype_get_font_properties(&stream_desc, &props); - hr = opentype_get_font_familyname(&stream_desc, &familynames); - IDWriteFontFile_Release(file); - IDWriteFontFileStream_Release(stream); - if (FAILED(hr)) - return hr; - - simulations = IDWriteFontFace_GetSimulations(fontface); + if (!fontface) + return E_INVALIDARG; + get_logfont_from_fontface(fontface, logfont); logfont->lfCharSet = DEFAULT_CHARSET; - logfont->lfWeight = props.weight; - logfont->lfItalic = props.style == DWRITE_FONT_STYLE_ITALIC || (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE); logfont->lfOutPrecision = OUT_OUTLINE_PRECIS; - logfont->lfFaceName[0] = 0; - exists = FALSE; - hr = IDWriteLocalizedStrings_FindLocaleName(familynames, enusW, &index, &exists); - if (FAILED(hr) || !exists) { - /* fallback to 0 index */ - if (IDWriteLocalizedStrings_GetCount(familynames) > 0) - index = 0; - else { - IDWriteLocalizedStrings_Release(familynames); - return E_FAIL; - } - } - - hr = IDWriteLocalizedStrings_GetString(familynames, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR)); - IDWriteLocalizedStrings_Release(familynames); - - return hr; + return S_OK; } struct font_realization_info { diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index ce4145eb81d..d5126fffbb9 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -2196,68 +2196,215 @@ static void test_system_fontcollection(void) IDWriteFactory_Release(factory); } +static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont) +{ + void *os2_context, *head_context; + IDWriteLocalizedStrings *names; + DWRITE_FONT_SIMULATIONS sim; + IDWriteFontFace *fontface; + const TT_OS2_V2 *tt_os2; + DWRITE_FONT_STYLE style; + const TT_HEAD *tt_head; + LONG weight; + UINT32 size; + BOOL exists; + HRESULT hr; + + /* These are rendering time properties. */ + logfont->lfHeight = 0; + logfont->lfWidth = 0; + logfont->lfEscapement = 0; + logfont->lfOrientation = 0; + logfont->lfUnderline = 0; + logfont->lfStrikeOut = 0; + + logfont->lfWeight = 0; + logfont->lfItalic = 0; + + hr = IDWriteFont_CreateFontFace(font, &fontface); + ok(hr == S_OK, "Failed to create font face, %#x\n", hr); + + hr = IDWriteFontFace_TryGetFontTable(fontface, MS_0S2_TAG, (const void **)&tt_os2, &size, + &os2_context, &exists); + ok(hr == S_OK, "Failed to get OS/2 table, %#x\n", hr); + + hr = IDWriteFontFace_TryGetFontTable(fontface, MS_HEAD_TAG, (const void **)&tt_head, &size, + &head_context, &exists); + ok(hr == S_OK, "Failed to get head table, %#x\n", hr); + + sim = IDWriteFont_GetSimulations(font); + + /* lfWeight */ + weight = FW_REGULAR; + if (tt_os2) { + USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass); + + if (usWeightClass >= 1 && usWeightClass <= 9) + usWeightClass *= 100; + + if (usWeightClass > DWRITE_FONT_WEIGHT_ULTRA_BLACK) + weight = DWRITE_FONT_WEIGHT_ULTRA_BLACK; + else if (usWeightClass > 0) + weight = usWeightClass; + } + else if (tt_head) { + USHORT macStyle = GET_BE_WORD(tt_head->macStyle); + if (macStyle & TT_HEAD_MACSTYLE_BOLD) + weight = DWRITE_FONT_WEIGHT_BOLD; + } + if (sim & DWRITE_FONT_SIMULATIONS_BOLD) + weight += (FW_BOLD - FW_REGULAR) / 2 + 1; + logfont->lfWeight = weight; + + /* lfItalic */ + if (IDWriteFont_GetSimulations(font) & DWRITE_FONT_SIMULATIONS_OBLIQUE) + logfont->lfItalic = 1; + + style = IDWriteFont_GetStyle(font); + if (!logfont->lfItalic && ((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE))) { + if (tt_os2) { + USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection); + logfont->lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC); + } + else if (tt_head) { + USHORT macStyle = GET_BE_WORD(tt_head->macStyle); + logfont->lfItalic = !!(macStyle & TT_HEAD_MACSTYLE_ITALIC); + } + } + + /* lfFaceName */ + exists = FALSE; + logfont->lfFaceName[0] = 0; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &exists); + if (SUCCEEDED(hr)) { + if (exists) { + static const WCHAR enusW[] = {'e','n','-','u','s',0}; + WCHAR localeW[LOCALE_NAME_MAX_LENGTH]; + UINT32 index; + + /* Fallback to en-us if there's no string for user locale. */ + exists = FALSE; + if (GetSystemDefaultLocaleName(localeW, sizeof(localeW)/sizeof(WCHAR))) + IDWriteLocalizedStrings_FindLocaleName(names, localeW, &index, &exists); + + if (!exists) + IDWriteLocalizedStrings_FindLocaleName(names, enusW, &index, &exists); + + if (exists) + IDWriteLocalizedStrings_GetString(names, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR)); + } + + IDWriteLocalizedStrings_Release(names); + } + + if (tt_os2) + IDWriteFontFace_ReleaseFontTable(fontface, os2_context); + if (tt_head) + IDWriteFontFace_ReleaseFontTable(fontface, head_context); + IDWriteFontFace_Release(fontface); +} + static void test_ConvertFontFaceToLOGFONT(void) { - DWRITE_FONT_SIMULATIONS sim; IDWriteGdiInterop *interop; IDWriteFontFace *fontface; IDWriteFactory *factory; - IDWriteFont *font; LOGFONTW logfont; + UINT32 count, i; HRESULT hr; + IDWriteFontCollection *collection; factory = create_factory(); hr = IDWriteFactory_GetGdiInterop(factory, &interop); ok(hr == S_OK, "got 0x%08x\n", hr); - memset(&logfont, 0, sizeof(logfont)); - logfont.lfHeight = 12; - logfont.lfWidth = 12; - logfont.lfEscapement = 100; - logfont.lfWeight = FW_NORMAL; - logfont.lfItalic = 1; - logfont.lfUnderline = 1; - logfont.lfStrikeOut = 1; - - lstrcpyW(logfont.lfFaceName, tahomaW); - - hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); - ok(hr == S_OK, "got 0x%08x\n", hr); - - hr = IDWriteFont_CreateFontFace(font, &fontface); - ok(hr == S_OK, "got 0x%08x\n", hr); - - sim = IDWriteFont_GetSimulations(font); - ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim); - - sim = IDWriteFontFace_GetSimulations(fontface); - ok(sim == DWRITE_FONT_SIMULATIONS_OBLIQUE, "sim %d\n", sim); - - IDWriteFont_Release(font); - if (0) /* crashes on native */ { hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, NULL); hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, NULL); } + memset(&logfont, 0xcc, sizeof(logfont)); + hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, NULL, &logfont); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(logfont.lfFaceName[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName)); - memset(&logfont, 0xa, sizeof(logfont)); - logfont.lfFaceName[0] = 0; - - hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont); + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight); - ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth); - ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight); - ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement); - ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic); - ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline); - ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut); - ok(!lstrcmpW(logfont.lfFaceName, tahomaW), "got %s\n", wine_dbgstr_w(logfont.lfFaceName)); + count = IDWriteFontCollection_GetFontFamilyCount(collection); + for (i = 0; i < count; i++) { + WCHAR nameW[128], familynameW[64], facenameW[64]; + IDWriteLocalizedStrings *names; + DWRITE_FONT_SIMULATIONS sim; + IDWriteFontFamily *family; + UINT32 font_count, j; + IDWriteFont *font; + LOGFONTW lf; + + hr = IDWriteFontCollection_GetFontFamily(collection, i, &family); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFontFamily_GetFamilyNames(family, &names); + ok(hr == S_OK, "got 0x%08x\n", hr); + + get_enus_string(names, familynameW, sizeof(familynameW)/sizeof(familynameW[0])); + IDWriteLocalizedStrings_Release(names); + + font_count = IDWriteFontFamily_GetFontCount(family); + + for (j = 0; j < font_count; j++) { + static const WCHAR spaceW[] = {' ', 0}; + IDWriteFontFace *fontface; + + hr = IDWriteFontFamily_GetFont(family, j, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFont_GetFaceNames(font, &names); + ok(hr == S_OK, "got 0x%08x\n", hr); + + get_enus_string(names, facenameW, sizeof(facenameW)/sizeof(facenameW[0])); + IDWriteLocalizedStrings_Release(names); + + lstrcpyW(nameW, familynameW); + lstrcatW(nameW, spaceW); + lstrcatW(nameW, facenameW); + + hr = IDWriteFont_CreateFontFace(font, &fontface); + ok(hr == S_OK, "got 0x%08x\n", hr); + + memset(&logfont, 0xcc, sizeof(logfont)); + hr = IDWriteGdiInterop_ConvertFontFaceToLOGFONT(interop, fontface, &logfont); + ok(hr == S_OK, "got 0x%08x\n", hr); + + sim = IDWriteFontFace_GetSimulations(fontface); + + get_logfont_from_font(font, &lf); + ok(logfont.lfWeight == lf.lfWeight, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, " + "bold simulation %s\n", wine_dbgstr_w(nameW), logfont.lfWeight, lf.lfWeight, IDWriteFont_GetWeight(font), + sim & DWRITE_FONT_SIMULATIONS_BOLD ? "yes" : "no"); + ok(logfont.lfItalic == lf.lfItalic, "%s: unexpected italic flag %d, oblique simulation %s\n", + wine_dbgstr_w(nameW), logfont.lfItalic, sim & DWRITE_FONT_SIMULATIONS_OBLIQUE ? "yes" : "no"); + ok(!lstrcmpW(logfont.lfFaceName, lf.lfFaceName), "%s: unexpected facename %s, expected %s\n", + wine_dbgstr_w(nameW), wine_dbgstr_w(logfont.lfFaceName), wine_dbgstr_w(lf.lfFaceName)); + + ok(logfont.lfOutPrecision == OUT_OUTLINE_PRECIS, "%s: unexpected output precision %d\n", wine_dbgstr_w(nameW), + logfont.lfOutPrecision); + ok(logfont.lfClipPrecision == CLIP_DEFAULT_PRECIS, "%s: unexpected clipping precision %d\n", wine_dbgstr_w(nameW), + logfont.lfClipPrecision); + ok(logfont.lfQuality == DEFAULT_QUALITY, "%s: unexpected quality %d\n", wine_dbgstr_w(nameW), logfont.lfQuality); + ok(logfont.lfPitchAndFamily == DEFAULT_PITCH, "%s: unexpected pitch %d\n", wine_dbgstr_w(nameW), + logfont.lfPitchAndFamily); + + IDWriteFontFace_Release(fontface); + IDWriteFont_Release(font); + } + + IDWriteFontFamily_Release(family); + } + + IDWriteFontCollection_Release(collection); IDWriteGdiInterop_Release(interop); - IDWriteFontFace_Release(fontface); IDWriteFactory_Release(factory); } @@ -3456,114 +3603,6 @@ static void test_TryGetFontTable(void) DELETE_FONTFILE(path); } -static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont) -{ - void *os2_context, *head_context; - IDWriteLocalizedStrings *names; - DWRITE_FONT_SIMULATIONS sim; - IDWriteFontFace *fontface; - const TT_OS2_V2 *tt_os2; - DWRITE_FONT_STYLE style; - const TT_HEAD *tt_head; - LONG weight; - UINT32 size; - BOOL exists; - HRESULT hr; - - /* These are rendering time properties. */ - logfont->lfHeight = 0; - logfont->lfWidth = 0; - logfont->lfEscapement = 0; - logfont->lfOrientation = 0; - logfont->lfUnderline = 0; - logfont->lfStrikeOut = 0; - - logfont->lfWeight = 0; - logfont->lfItalic = 0; - - hr = IDWriteFont_CreateFontFace(font, &fontface); - ok(hr == S_OK, "Failed to create font face, %#x\n", hr); - - hr = IDWriteFontFace_TryGetFontTable(fontface, MS_0S2_TAG, (const void **)&tt_os2, &size, - &os2_context, &exists); - ok(hr == S_OK, "Failed to get OS/2 table, %#x\n", hr); - - hr = IDWriteFontFace_TryGetFontTable(fontface, MS_HEAD_TAG, (const void **)&tt_head, &size, - &head_context, &exists); - ok(hr == S_OK, "Failed to get head table, %#x\n", hr); - - sim = IDWriteFont_GetSimulations(font); - - /* lfWeight */ - weight = FW_REGULAR; - if (tt_os2) { - USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass); - - if (usWeightClass >= 1 && usWeightClass <= 9) - usWeightClass *= 100; - - if (usWeightClass > DWRITE_FONT_WEIGHT_ULTRA_BLACK) - weight = DWRITE_FONT_WEIGHT_ULTRA_BLACK; - else if (usWeightClass > 0) - weight = usWeightClass; - } - else if (tt_head) { - USHORT macStyle = GET_BE_WORD(tt_head->macStyle); - if (macStyle & TT_HEAD_MACSTYLE_BOLD) - weight = DWRITE_FONT_WEIGHT_BOLD; - } - if (sim & DWRITE_FONT_SIMULATIONS_BOLD) - weight += (FW_BOLD - FW_REGULAR) / 2 + 1; - logfont->lfWeight = weight; - - /* lfItalic */ - if (IDWriteFont_GetSimulations(font) & DWRITE_FONT_SIMULATIONS_OBLIQUE) - logfont->lfItalic = 1; - - style = IDWriteFont_GetStyle(font); - if (!logfont->lfItalic && ((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE))) { - if (tt_os2) { - USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection); - logfont->lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC); - } - else if (tt_head) { - USHORT macStyle = GET_BE_WORD(tt_head->macStyle); - logfont->lfItalic = !!(macStyle & TT_HEAD_MACSTYLE_ITALIC); - } - } - - /* lfFaceName */ - exists = FALSE; - logfont->lfFaceName[0] = 0; - hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &exists); - if (SUCCEEDED(hr)) { - if (exists) { - static const WCHAR enusW[] = {'e','n','-','u','s',0}; - WCHAR localeW[LOCALE_NAME_MAX_LENGTH]; - UINT32 index; - - /* Fallback to en-us if there's no string for user locale. */ - exists = FALSE; - if (GetSystemDefaultLocaleName(localeW, sizeof(localeW)/sizeof(WCHAR))) - IDWriteLocalizedStrings_FindLocaleName(names, localeW, &index, &exists); - - if (!exists) - IDWriteLocalizedStrings_FindLocaleName(names, enusW, &index, &exists); - - if (exists) - IDWriteLocalizedStrings_GetString(names, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR)); - } - - IDWriteLocalizedStrings_Release(names); - } - - if (tt_os2) - IDWriteFontFace_ReleaseFontTable(fontface, os2_context); - if (tt_head) - IDWriteFontFace_ReleaseFontTable(fontface, head_context); - IDWriteFontFace_Release(fontface); -} - static void test_ConvertFontToLOGFONT(void) { IDWriteFactory *factory, *factory2;