dwrite: Improve returned font metrics when OS/2 table is missing.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2018-11-11 09:55:00 +03:00 committed by Alexandre Julliard
parent 95fa795fa1
commit 9fb74b68a4
2 changed files with 131 additions and 89 deletions

View File

@ -1309,6 +1309,13 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT
metrics->hasTypographicMetrics = TRUE; metrics->hasTypographicMetrics = TRUE;
} }
} }
else {
metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
if (tt_hhea) {
metrics->ascent = GET_BE_WORD(tt_hhea->ascender);
metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender));
}
}
if (tt_post) { if (tt_post) {
metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition); metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);

View File

@ -511,6 +511,27 @@ static void _delete_testfontfile(const WCHAR *filename, int line)
ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError()); ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
} }
static void get_combined_font_name(const WCHAR *familyW, const WCHAR *faceW, WCHAR *nameW)
{
static const WCHAR spaceW[] = {' ', 0};
lstrcpyW(nameW, familyW);
lstrcatW(nameW, spaceW);
lstrcatW(nameW, faceW);
}
static BOOL has_face_variations(IDWriteFontFace *fontface)
{
IDWriteFontFace5 *fontface5;
BOOL ret = FALSE;
if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5))) {
ret = IDWriteFontFace5_HasVariations(fontface5);
IDWriteFontFace5_Release(fontface5);
}
return ret;
}
struct test_fontenumerator struct test_fontenumerator
{ {
IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface; IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
@ -1916,6 +1937,13 @@ static void get_expected_font_metrics(IDWriteFontFace *fontface, DWRITE_FONT_MET
metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize); metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize);
metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize); metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize);
} }
else {
metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
if (tt_hhea) {
metrics->ascent = GET_BE_WORD(tt_hhea->ascender);
metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender));
}
}
if (tt_post) { if (tt_post) {
metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition); metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);
@ -1937,55 +1965,72 @@ static void get_expected_font_metrics(IDWriteFontFace *fontface, DWRITE_FONT_MET
IDWriteFontFace_ReleaseFontTable(fontface, post_context); IDWriteFontFace_ReleaseFontTable(fontface, post_context);
} }
static void check_font_metrics(const WCHAR *nameW, BOOL has_metrics1, const DWRITE_FONT_METRICS *got, static void check_font_metrics(const WCHAR *nameW, IDWriteFontFace *fontface, const DWRITE_FONT_METRICS1 *expected)
const DWRITE_FONT_METRICS1 *expected)
{ {
ok(got->designUnitsPerEm == expected->designUnitsPerEm, "font %s: designUnitsPerEm %u, expected %u\n", IDWriteFontFace1 *fontface1 = NULL;
wine_dbgstr_w(nameW), got->designUnitsPerEm, expected->designUnitsPerEm); DWRITE_FONT_METRICS1 metrics;
ok(got->ascent == expected->ascent, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW), got->ascent, DWORD simulations;
BOOL has_metrics1;
has_metrics1 = SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1));
simulations = IDWriteFontFace_GetSimulations(fontface);
if (fontface1) {
IDWriteFontFace1_GetMetrics(fontface1, &metrics);
IDWriteFontFace1_Release(fontface1);
}
else
IDWriteFontFace_GetMetrics(fontface, (DWRITE_FONT_METRICS *)&metrics);
ok(metrics.designUnitsPerEm == expected->designUnitsPerEm, "font %s: designUnitsPerEm %u, expected %u\n",
wine_dbgstr_w(nameW), metrics.designUnitsPerEm, expected->designUnitsPerEm);
ok(metrics.ascent == expected->ascent, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW), metrics.ascent,
expected->ascent); expected->ascent);
ok(got->descent == expected->descent, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW), got->descent, ok(metrics.descent == expected->descent, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW),
expected->descent); metrics.descent, expected->descent);
ok(got->lineGap == expected->lineGap, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW), got->lineGap, ok(metrics.lineGap == expected->lineGap, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW),
expected->lineGap); metrics.lineGap, expected->lineGap);
ok(got->underlinePosition == expected->underlinePosition, "font %s: underlinePosition %d, expected %d\n", ok(metrics.underlinePosition == expected->underlinePosition, "font %s: underlinePosition %d, expected %d\n",
wine_dbgstr_w(nameW), got->underlinePosition, expected->underlinePosition); wine_dbgstr_w(nameW), metrics.underlinePosition, expected->underlinePosition);
ok(got->underlineThickness == expected->underlineThickness, "font %s: underlineThickness %u, " ok(metrics.underlineThickness == expected->underlineThickness, "font %s: underlineThickness %u, "
"expected %u\n", wine_dbgstr_w(nameW), got->underlineThickness, expected->underlineThickness); "expected %u\n", wine_dbgstr_w(nameW), metrics.underlineThickness, expected->underlineThickness);
ok(got->strikethroughPosition == expected->strikethroughPosition, "font %s: strikethroughPosition %d, expected %d\n", ok(metrics.strikethroughPosition == expected->strikethroughPosition, "font %s: strikethroughPosition %d, expected %d\n",
wine_dbgstr_w(nameW), got->strikethroughPosition, expected->strikethroughPosition); wine_dbgstr_w(nameW), metrics.strikethroughPosition, expected->strikethroughPosition);
ok(got->strikethroughThickness == expected->strikethroughThickness, "font %s: strikethroughThickness %u, " ok(metrics.strikethroughThickness == expected->strikethroughThickness, "font %s: strikethroughThickness %u, "
"expected %u\n", wine_dbgstr_w(nameW), got->strikethroughThickness, expected->strikethroughThickness); "expected %u\n", wine_dbgstr_w(nameW), metrics.strikethroughThickness, expected->strikethroughThickness);
if (has_metrics1) { if (has_metrics1) {
const DWRITE_FONT_METRICS1 *m1 = (const DWRITE_FONT_METRICS1*)got; /* For simulated faces metrics are adjusted. Enable tests when exact pattern is understood. */
ok(m1->hasTypographicMetrics == expected->hasTypographicMetrics, "font %s: hasTypographicMetrics %d, " if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE)
"expected %d\n", wine_dbgstr_w(nameW), m1->hasTypographicMetrics, expected->hasTypographicMetrics); return;
ok(m1->glyphBoxLeft == expected->glyphBoxLeft, "font %s: glyphBoxLeft %d, expected %d\n", wine_dbgstr_w(nameW),
m1->glyphBoxLeft, expected->glyphBoxLeft);
ok(m1->glyphBoxTop == expected->glyphBoxTop, "font %s: glyphBoxTop %d, expected %d\n", wine_dbgstr_w(nameW),
m1->glyphBoxTop, expected->glyphBoxTop);
ok(m1->glyphBoxRight == expected->glyphBoxRight, "font %s: glyphBoxRight %d, expected %d\n", wine_dbgstr_w(nameW),
m1->glyphBoxRight, expected->glyphBoxRight);
ok(m1->glyphBoxBottom == expected->glyphBoxBottom, "font %s: glyphBoxBottom %d, expected %d\n", wine_dbgstr_w(nameW),
m1->glyphBoxBottom, expected->glyphBoxBottom);
ok(m1->subscriptPositionX == expected->subscriptPositionX, "font %s: subscriptPositionX %d, expected %d\n", ok(metrics.hasTypographicMetrics == expected->hasTypographicMetrics, "font %s: hasTypographicMetrics %d, "
wine_dbgstr_w(nameW), m1->subscriptPositionX, expected->subscriptPositionX); "expected %d\n", wine_dbgstr_w(nameW), metrics.hasTypographicMetrics, expected->hasTypographicMetrics);
ok(m1->subscriptPositionY == expected->subscriptPositionY, "font %s: subscriptPositionY %d, expected %d\n", ok(metrics.glyphBoxLeft == expected->glyphBoxLeft, "font %s: glyphBoxLeft %d, expected %d\n",
wine_dbgstr_w(nameW), m1->subscriptPositionY, expected->subscriptPositionY); wine_dbgstr_w(nameW), metrics.glyphBoxLeft, expected->glyphBoxLeft);
ok(m1->subscriptSizeX == expected->subscriptSizeX, "font %s: subscriptSizeX %d, expected %d\n", ok(metrics.glyphBoxTop == expected->glyphBoxTop, "font %s: glyphBoxTop %d, expected %d\n",
wine_dbgstr_w(nameW), m1->subscriptSizeX, expected->subscriptSizeX); wine_dbgstr_w(nameW), metrics.glyphBoxTop, expected->glyphBoxTop);
ok(m1->subscriptSizeY == expected->subscriptSizeY, "font %s: subscriptSizeY %d, expected %d\n", ok(metrics.glyphBoxRight == expected->glyphBoxRight, "font %s: glyphBoxRight %d, expected %d\n",
wine_dbgstr_w(nameW), m1->subscriptSizeY, expected->subscriptSizeY); wine_dbgstr_w(nameW), metrics.glyphBoxRight, expected->glyphBoxRight);
ok(m1->superscriptPositionX == expected->superscriptPositionX, "font %s: superscriptPositionX %d, expected %d\n", ok(metrics.glyphBoxBottom == expected->glyphBoxBottom, "font %s: glyphBoxBottom %d, expected %d\n",
wine_dbgstr_w(nameW), m1->superscriptPositionX, expected->superscriptPositionX); wine_dbgstr_w(nameW), metrics.glyphBoxBottom, expected->glyphBoxBottom);
ok(m1->superscriptPositionY == expected->superscriptPositionY, "font %s: superscriptPositionY %d, expected %d\n",
wine_dbgstr_w(nameW), m1->superscriptPositionY, expected->superscriptPositionY); ok(metrics.subscriptPositionX == expected->subscriptPositionX, "font %s: subscriptPositionX %d, expected %d\n",
ok(m1->superscriptSizeX == expected->superscriptSizeX, "font %s: superscriptSizeX %d, expected %d\n", wine_dbgstr_w(nameW), metrics.subscriptPositionX, expected->subscriptPositionX);
wine_dbgstr_w(nameW), m1->superscriptSizeX, expected->superscriptSizeX); ok(metrics.subscriptPositionY == expected->subscriptPositionY, "font %s: subscriptPositionY %d, expected %d\n",
ok(m1->superscriptSizeY == expected->superscriptSizeY, "font %s: superscriptSizeY %d, expected %d\n", wine_dbgstr_w(nameW), metrics.subscriptPositionY, expected->subscriptPositionY);
wine_dbgstr_w(nameW), m1->superscriptSizeY, expected->superscriptSizeY); ok(metrics.subscriptSizeX == expected->subscriptSizeX, "font %s: subscriptSizeX %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.subscriptSizeX, expected->subscriptSizeX);
ok(metrics.subscriptSizeY == expected->subscriptSizeY, "font %s: subscriptSizeY %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.subscriptSizeY, expected->subscriptSizeY);
ok(metrics.superscriptPositionX == expected->superscriptPositionX, "font %s: superscriptPositionX %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.superscriptPositionX, expected->superscriptPositionX);
ok(metrics.superscriptPositionY == expected->superscriptPositionY, "font %s: superscriptPositionY %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.superscriptPositionY, expected->superscriptPositionY);
ok(metrics.superscriptSizeX == expected->superscriptSizeX, "font %s: superscriptSizeX %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.superscriptSizeX, expected->superscriptSizeX);
ok(metrics.superscriptSizeY == expected->superscriptSizeY, "font %s: superscriptSizeY %d, expected %d\n",
wine_dbgstr_w(nameW), metrics.superscriptSizeY, expected->superscriptSizeY);
} }
} }
@ -2195,47 +2240,53 @@ static void test_GetMetrics(void)
count = IDWriteFontCollection_GetFontFamilyCount(syscollection); count = IDWriteFontCollection_GetFontFamilyCount(syscollection);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
DWRITE_FONT_METRICS1 expected_metrics, metrics1; DWRITE_FONT_METRICS1 expected_metrics;
WCHAR familyW[256], faceW[256];
IDWriteLocalizedStrings *names; IDWriteLocalizedStrings *names;
IDWriteFontFace1 *fontface1;
IDWriteFontFamily *family; IDWriteFontFamily *family;
UINT32 fontcount, j;
IDWriteFont *font; IDWriteFont *font;
WCHAR nameW[256];
hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family); hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, fontcount = IDWriteFontFamily_GetFontCount(family);
DWRITE_FONT_STYLE_NORMAL, &font);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFont_CreateFontFace(font, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr);
fontface1 = NULL;
IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
hr = IDWriteFontFamily_GetFamilyNames(family, &names); hr = IDWriteFontFamily_GetFamilyNames(family, &names);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "Failed to get family names, hr %#x.\n", hr);
get_enus_string(names, familyW, ARRAY_SIZE(familyW));
get_enus_string(names, nameW, ARRAY_SIZE(nameW));
IDWriteLocalizedStrings_Release(names); IDWriteLocalizedStrings_Release(names);
IDWriteFont_Release(font);
get_expected_font_metrics(fontface, &expected_metrics); for (j = 0; j < fontcount; j++) {
if (fontface1) { WCHAR nameW[256];
IDWriteFontFace1_GetMetrics(fontface1, &metrics1);
check_font_metrics(nameW, TRUE, (const DWRITE_FONT_METRICS*)&metrics1, &expected_metrics); hr = IDWriteFontFamily_GetFont(family, j, &font);
} ok(hr == S_OK, "Failed to get a font, hr %#x.\n", hr);
else {
IDWriteFontFace_GetMetrics(fontface, &metrics); hr = IDWriteFont_CreateFontFace(font, &fontface);
check_font_metrics(nameW, FALSE, &metrics, &expected_metrics); ok(hr == S_OK, "Failed to create face instance, hr %#x.\n", hr);
hr = IDWriteFont_GetFaceNames(font, &names);
ok(hr == S_OK, "Failed to get face names, hr %#x.\n", hr);
get_enus_string(names, faceW, ARRAY_SIZE(faceW));
IDWriteLocalizedStrings_Release(names);
IDWriteFont_Release(font);
get_combined_font_name(familyW, faceW, nameW);
if (has_face_variations(fontface)) {
skip("%s: test does not support variable fonts.\n", wine_dbgstr_w(nameW));
IDWriteFontFace_Release(fontface);
continue;
}
get_expected_font_metrics(fontface, &expected_metrics);
check_font_metrics(nameW, fontface, &expected_metrics);
IDWriteFontFace_Release(fontface);
} }
if (fontface1)
IDWriteFontFace1_Release(fontface1);
IDWriteFontFace_Release(fontface);
IDWriteFontFamily_Release(family); IDWriteFontFamily_Release(family);
} }
IDWriteFontCollection_Release(syscollection); IDWriteFontCollection_Release(syscollection);
@ -2542,19 +2593,6 @@ static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
IDWriteFontFace_Release(fontface); IDWriteFontFace_Release(fontface);
} }
static BOOL has_face_variations(IDWriteFontFace *fontface)
{
IDWriteFontFace5 *fontface5;
BOOL ret = FALSE;
if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5))) {
ret = IDWriteFontFace5_HasVariations(fontface5);
IDWriteFontFace5_Release(fontface5);
}
return ret;
}
static void test_ConvertFontFaceToLOGFONT(void) static void test_ConvertFontFaceToLOGFONT(void)
{ {
IDWriteFontCollection *collection; IDWriteFontCollection *collection;
@ -2606,7 +2644,6 @@ if (0) /* crashes on native */
font_count = IDWriteFontFamily_GetFontCount(family); font_count = IDWriteFontFamily_GetFontCount(family);
for (j = 0; j < font_count; j++) { for (j = 0; j < font_count; j++) {
static const WCHAR spaceW[] = {' ', 0};
IDWriteFontFace *fontface; IDWriteFontFace *fontface;
hr = IDWriteFontFamily_GetFont(family, j, &font); hr = IDWriteFontFamily_GetFont(family, j, &font);
@ -2618,9 +2655,7 @@ if (0) /* crashes on native */
get_enus_string(names, facenameW, ARRAY_SIZE(facenameW)); get_enus_string(names, facenameW, ARRAY_SIZE(facenameW));
IDWriteLocalizedStrings_Release(names); IDWriteLocalizedStrings_Release(names);
lstrcpyW(nameW, familynameW); get_combined_font_name(familynameW, facenameW, nameW);
lstrcatW(nameW, spaceW);
lstrcatW(nameW, facenameW);
hr = IDWriteFont_CreateFontFace(font, &fontface); hr = IDWriteFont_CreateFontFace(font, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);