dwrite: Improve ConvertFontFaceToLOGFONT using same logic IDWriteFont uses.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-12-07 16:46:39 +03:00 committed by Alexandre Julliard
parent bf23b8a529
commit c22b2192e5
4 changed files with 210 additions and 200 deletions

View file

@ -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 {

View file

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

View file

@ -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 {

View file

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