From: Akihiro Sagawa Subject: [PATCH 1/4] gdi32: Fix ABC width calculations when applying transformations internally. Message-Id: <20180204210023.10A4.375B48EC@gmail.com> Date: Sun, 04 Feb 2018 21:02:07 +0900 This fixes a regression introduced by f6bc356860a1ea2e5b4aed43e38ddf8b7d24a8b0. Fixes Bug 43256. Signed-off-by: Akihiro Sagawa --- dlls/gdi32/freetype.c | 15 ++++++++------- dlls/gdi32/tests/font.c | 44 +++++++++++++++++++------------------------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 4db1c7e..7016095 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -7008,7 +7008,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, origin_x = left; origin_y = top; abc->abcA = origin_x >> 6; - abc->abcB = metrics.width >> 6; + abc->abcB = (metrics.width + 63) >> 6; } else { INT xc, yc; FT_Vector vec; @@ -7064,19 +7064,20 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, gm.gmCellIncY = adv.y >> 6; adv = get_advance_metric(incoming_font, font, &metrics, &transMatUnrotated, vertical_metrics); + adv.x = pFT_Vector_Length(&adv); + adv.y = 0; vec.x = lsb; vec.y = 0; pFT_Vector_Transform(&vec, &transMatUnrotated); - abc->abcA = vec.x >> 6; + if(lsb > 0) abc->abcA = pFT_Vector_Length(&vec) >> 6; + else abc->abcA = -((pFT_Vector_Length(&vec) + 63) >> 6); - vec.x = metrics.width; + /* We use lsb again to avoid rounding errors */ + vec.x = lsb + metrics.width; vec.y = 0; pFT_Vector_Transform(&vec, &transMatUnrotated); - if (vec.x >= 0) - abc->abcB = vec.x >> 6; - else - abc->abcB = -vec.x >> 6; + abc->abcB = ((pFT_Vector_Length(&vec) + 63) >> 6) - abc->abcA; } width = (right - left) >> 6; diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 70e44f3..4bac19a 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -1128,7 +1128,7 @@ static int CALLBACK create_font_proc(const LOGFONTA *lpelfe, return 1; } -static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, ABC *base_abci, ABC *base_abcw, ABCFLOAT *base_abcf, INT todo) +static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf) { ABC abc[1]; ABCFLOAT abcf[1]; @@ -1137,26 +1137,20 @@ static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, ABC ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc); ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description); ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description); - todo_wine_if (todo) - ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description); - todo_wine_if (todo) - ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description); + ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description); + ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description); ret = pGetCharABCWidthsW(hdc, 'i', 'i', abc); ok(ret, "%s: GetCharABCWidthsW should have succeeded\n", description); ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description); - todo_wine_if (todo) - ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description); - todo_wine_if (todo) - ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description); + ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description); + ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description); ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf); ok(ret, "%s: GetCharABCWidthsFloatW should have succeeded\n", description); ok (abcf->abcfB > 0.0, "%s: abcfB should be positive\n", description); - todo_wine_if (todo) - ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description); - todo_wine_if (todo) - ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description); + ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description); + ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description); } static void test_GetCharABCWidths(void) @@ -1369,17 +1363,17 @@ static void test_GetCharABCWidths(void) ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf); ok(ret, "GetCharABCWidthsFloatW should have succeeded\n"); - ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf); SetWindowExtEx(hdc, -1, -1, NULL); SetGraphicsMode(hdc, GM_COMPATIBLE); - ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf); SetGraphicsMode(hdc, GM_ADVANCED); - ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf, 1); + ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf); SetWindowExtEx(hdc, 1, 1, NULL); SetGraphicsMode(hdc, GM_COMPATIBLE); - ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf); SetGraphicsMode(hdc, GM_ADVANCED); - ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); @@ -1391,17 +1385,17 @@ static void test_GetCharABCWidths(void) SetMapMode(hdc, MM_ANISOTROPIC); SelectObject(hdc, hfont); - ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf); SetWindowExtEx(hdc, -1, -1, NULL); SetGraphicsMode(hdc, GM_COMPATIBLE); - ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf); SetGraphicsMode(hdc, GM_ADVANCED); - ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf); SetWindowExtEx(hdc, 1, 1, NULL); SetGraphicsMode(hdc, GM_COMPATIBLE); - ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf, 0); + ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf); SetGraphicsMode(hdc, GM_ADVANCED); - ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf, 1); + ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); @@ -6372,7 +6366,7 @@ static void test_GetCharWidth32(void) SetGraphicsMode(hdc, GM_ADVANCED); ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW); ok(ret, "GetCharWidth32W should have succeeded\n"); - todo_wine ok (bufferW > 0," Width should be greater than zero\n"); + ok (bufferW > 0," Width should be greater than zero\n"); SetWindowExtEx(hdc, 1,1,NULL); SetGraphicsMode(hdc, GM_COMPATIBLE); ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW); @@ -6412,7 +6406,7 @@ static void test_GetCharWidth32(void) SetGraphicsMode(hdc, GM_ADVANCED); ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW); ok(ret, "GetCharWidth32W should have succeeded\n"); - todo_wine ok (bufferW > 0," Width should be greater than zero\n"); + ok (bufferW > 0," Width should be greater than zero\n"); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd);