diff --git a/modules/rostests/apitests/gdi32/GetGlyphOutline.c b/modules/rostests/apitests/gdi32/GetGlyphOutline.c index c2d16f5a70e..e1fd700898f 100644 --- a/modules/rostests/apitests/gdi32/GetGlyphOutline.c +++ b/modules/rostests/apitests/gdi32/GetGlyphOutline.c @@ -6,6 +6,7 @@ */ #include "precomp.h" +#include "undocgdi.h" typedef struct TEST_ENTRY { @@ -298,11 +299,10 @@ static const TEST_ENTRY s_entries[] = { __LINE__, L"Marlett", -14, 36, 0xDEADBEEF, WCH5, GGO_BITMAP, TRUE, { 6, 9, { 0, 9 }, 7, 0 }, 512, s_ab }, }; -void DoEntry(const TEST_ENTRY *pEntry) +static void DoEntryW(HDC hDC, const TEST_ENTRY *pEntry) { LOGFONTW lf; HFONT hFont; - HDC hDC; HGDIOBJ hFontOld; ZeroMemory(&lf, sizeof(lf)); @@ -319,15 +319,6 @@ void DoEntry(const TEST_ENTRY *pEntry) return; } - hDC = CreateCompatibleDC(NULL); - ok(hDC != NULL, "hDC was NULL\n"); - if (hDC == NULL) - { - skip("Line %d: skipped because hDC == NULL\n", pEntry->line); - DeleteObject(hFont); - return; - } - hFontOld = SelectObject(hDC, hFont); ok(hFontOld != NULL, "SelectObject failed\n"); if (hFontOld == NULL) @@ -368,14 +359,93 @@ void DoEntry(const TEST_ENTRY *pEntry) } DeleteObject(hFont); - DeleteDC(hDC); } -START_TEST(GetGlyphOutline) +static void TEST_GetGlyphOutlineW(HDC hDC) { SIZE_T i, count = ARRAYSIZE(s_entries); for (i = 0; i < count; ++i) { - DoEntry(&s_entries[i]); + DoEntryW(hDC, &s_entries[i]); } } + +static void TEST_GetGlyphOutlineA(HDC hDC) +{ + LOGFONTW lf; + ZeroMemory(&lf, sizeof(lf)); + lf.lfHeight = 100; + lf.lfCharSet = DEFAULT_CHARSET; + lstrcpynW(lf.lfFaceName, L"Arial", _countof(lf.lfFaceName)); + HFONT hFont = CreateFontIndirectW(&lf); + ok(hFont != NULL, "hFont was NULL\n"); + + HGDIOBJ hFontOld = SelectObject(hDC, hFont); + + GLYPHMETRICS gm; + ZeroMemory(&gm, sizeof(gm)); + + DWORD ret; + + ret = GetGlyphOutlineA(hDC, 'A', GGO_NATIVE, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR && ret != 0, "ret was 0x%lX\n", ret); + + ret = GetGlyphOutlineA(hDC, 'A', GGO_BITMAP, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR && ret != 0, "ret was 0x%lX\n", ret); + + ret = GetGlyphOutlineA(hDC, 'A', GGO_METRICS, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR, "ret was 0x%lX\n", ret); + + SelectObject(hDC, hFontOld); + DeleteObject(hFont); +} + +typedef DWORD (WINAPI *FN_GetGlyphOutlineWow)(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, CONST MAT2 *); + +static void TEST_GetGlyphOutlineWow(HDC hDC) +{ + HINSTANCE hGDI32 = GetModuleHandleA("gdi32"); + FN_GetGlyphOutlineWow fnGetGlyphOutlineWow = + (FN_GetGlyphOutlineWow)GetProcAddress(hGDI32, "GetGlyphOutlineWow"); + if (!fnGetGlyphOutlineWow) + { + skip("GetGlyphOutlineWow not found\n"); + return; + } + + LOGFONTW lf; + ZeroMemory(&lf, sizeof(lf)); + lf.lfHeight = 100; + lf.lfCharSet = DEFAULT_CHARSET; + lstrcpynW(lf.lfFaceName, L"Arial", _countof(lf.lfFaceName)); + HFONT hFont = CreateFontIndirectW(&lf); + ok(hFont != NULL, "hFont was NULL\n"); + + HGDIOBJ hFontOld = SelectObject(hDC, hFont); + + GLYPHMETRICS gm; + ZeroMemory(&gm, sizeof(gm)); + + DWORD ret; + + ret = fnGetGlyphOutlineWow(hDC, 'A', GGO_NATIVE, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR && ret != 0, "ret was 0x%lX\n", ret); + + ret = fnGetGlyphOutlineWow(hDC, 'A', GGO_BITMAP, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR && ret != 0, "ret was 0x%lX\n", ret); + + ret = fnGetGlyphOutlineWow(hDC, 'A', GGO_METRICS, &gm, 0, NULL, &s_mat); + ok(ret != GDI_ERROR, "ret was 0x%lX\n", ret); + + SelectObject(hDC, hFontOld); + DeleteObject(hFont); +} + +START_TEST(GetGlyphOutline) +{ + HDC hDC = CreateCompatibleDC(NULL); + TEST_GetGlyphOutlineW(hDC); + TEST_GetGlyphOutlineA(hDC); + TEST_GetGlyphOutlineWow(hDC); + DeleteDC(hDC); +} diff --git a/sdk/include/reactos/undocgdi.h b/sdk/include/reactos/undocgdi.h index 34f49811285..e5033cf9b83 100644 --- a/sdk/include/reactos/undocgdi.h +++ b/sdk/include/reactos/undocgdi.h @@ -49,6 +49,16 @@ GetFontResourceInfoW( _Out_writes_to_opt_(*pdwBufSize, 1) PVOID lpBuffer, _In_ DWORD dwType); +DWORD WINAPI +GetGlyphOutlineWow( + _In_ HDC hdc, + _In_ UINT uChar, + _In_ UINT fuFormat, + _Out_ LPGLYPHMETRICS lpgm, + _In_ DWORD cbBuffer, + _Out_writes_bytes_opt_(cbBuffer) LPVOID lpvBuffer, + _In_ CONST MAT2 *lpmat2); + #ifdef __cplusplus } // extern "C" #endif diff --git a/win32ss/gdi/gdi32/gdi32.spec b/win32ss/gdi/gdi32/gdi32.spec index c6658cceaab..01829b19ac1 100644 --- a/win32ss/gdi/gdi32/gdi32.spec +++ b/win32ss/gdi/gdi32/gdi32.spec @@ -385,7 +385,7 @@ 385 stdcall GetGlyphOutline(long long long ptr long ptr ptr) GetGlyphOutlineA 386 stdcall GetGlyphOutlineA(long long long ptr long ptr ptr) 387 stdcall GetGlyphOutlineW(long long long ptr long ptr ptr) -388 stdcall GetGlyphOutlineWow(long long long long long long long) +388 stdcall GetGlyphOutlineWow(long long long ptr long ptr ptr) 389 stdcall GetGraphicsMode(long) 390 stdcall GetHFONT(ptr) 391 stdcall GetICMProfileA(long ptr ptr) diff --git a/win32ss/gdi/gdi32/objects/font.c b/win32ss/gdi/gdi32/objects/font.c index e5384e60e1a..96b353ba29b 100644 --- a/win32ss/gdi/gdi32/objects/font.c +++ b/win32ss/gdi/gdi32/objects/font.c @@ -13,6 +13,7 @@ #include #include +#include #define NDEBUG #include @@ -1127,94 +1128,120 @@ GetGlyphIndicesA( return Ret; } -/* - * @implemented - */ -DWORD -WINAPI -GetGlyphOutlineA( - HDC hdc, - UINT uChar, - UINT uFormat, - LPGLYPHMETRICS lpgm, - DWORD cbBuffer, - LPVOID lpvBuffer, - CONST MAT2 *lpmat2 -) +static __inline DWORD APIENTRY +IntGetGlyphOutlineW( + HDC hdc, + UINT uChar, + UINT fuFormat, + LPGLYPHMETRICS lpgm, + DWORD cbBuffer, + LPVOID lpvBuffer, + CONST MAT2 *lpmat2, + BOOL bIgnoreRotation) { + if (!lpmat2 || !lpgm) + return GDI_ERROR; + if (!lpvBuffer) + cbBuffer = 0; + return NtGdiGetGlyphOutline(hdc, uChar, fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, + bIgnoreRotation); +} - LPWSTR p = NULL; - DWORD ret; - UINT c; - DPRINT("GetGlyphOutlineA uChar %x\n", uChar); - if (!lpgm || !lpmat2) return GDI_ERROR; - if(!(uFormat & GGO_GLYPH_INDEX)) +static DWORD APIENTRY +IntGetGlyphOutlineA( + HDC hdc, + UINT uChar, + UINT fuFormat, + LPGLYPHMETRICS lpgm, + DWORD cbBuffer, + LPVOID lpvBuffer, + CONST MAT2 *lpmat2, + BOOL bIgnoreRotation) +{ + UINT nCodePage, cchAnsi; + CHAR szAnsi[4]; + WCHAR szWide[2]; + + if (fuFormat & GGO_GLYPH_INDEX) { - int len; - char mbchs[2]; - if(uChar > 0xff) /* but, 2 bytes character only */ - { - len = 2; - mbchs[0] = (uChar & 0xff00) >> 8; - mbchs[1] = (uChar & 0xff); - } - else - { - len = 1; - mbchs[0] = (uChar & 0xff); - } - p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL); - if(!p) - return GDI_ERROR; - c = p[0]; + szWide[0] = (WCHAR)uChar; + return IntGetGlyphOutlineW(hdc, szWide[0], fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, + bIgnoreRotation); + } + + nCodePage = GdiGetCodePage(hdc); + if ((nCodePage == CP_SHIFTJIS || + nCodePage == CP_HANGUL || + nCodePage == CP_BIG5 || + nCodePage == CP_GB2312) && IsDBCSLeadByteEx(nCodePage, HIBYTE(uChar))) + { + szAnsi[0] = HIBYTE(uChar); + szAnsi[1] = LOBYTE(uChar); + cchAnsi = 2; } else - c = uChar; - ret = NtGdiGetGlyphOutline(hdc, c, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); - HeapFree(GetProcessHeap(), 0, p); - return ret; + { + szAnsi[0] = LOBYTE(uChar); + cchAnsi = 1; + } + + if (!MultiByteToWideChar(nCodePage, 0, szAnsi, cchAnsi, szWide, _countof(szWide))) + { + GdiSetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + return IntGetGlyphOutlineW(hdc, szWide[0], fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, + bIgnoreRotation); +} + +/* + * @implemented + */ +DWORD WINAPI +GetGlyphOutlineA( + _In_ HDC hdc, + _In_ UINT uChar, + _In_ UINT fuFormat, + _Out_ LPGLYPHMETRICS lpgm, + _In_ DWORD cbBuffer, + _Out_writes_bytes_opt_(cbBuffer) LPVOID lpvBuffer, + _In_ CONST MAT2 *lpmat2) +{ + return IntGetGlyphOutlineA(hdc, uChar, fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, FALSE); } /* * @implemented */ -DWORD -WINAPI +DWORD WINAPI GetGlyphOutlineW( - HDC hdc, - UINT uChar, - UINT uFormat, - LPGLYPHMETRICS lpgm, - DWORD cbBuffer, - LPVOID lpvBuffer, - CONST MAT2 *lpmat2 -) + _In_ HDC hdc, + _In_ UINT uChar, + _In_ UINT fuFormat, + _Out_ LPGLYPHMETRICS lpgm, + _In_ DWORD cbBuffer, + _Out_writes_bytes_opt_(cbBuffer) LPVOID lpvBuffer, + _In_ CONST MAT2 *lpmat2) { - DPRINT("GetGlyphOutlineW uChar %x\n", uChar); - if (!lpgm || !lpmat2) return GDI_ERROR; - if (!lpvBuffer) cbBuffer = 0; - return NtGdiGetGlyphOutline ( hdc, uChar, uFormat, lpgm, cbBuffer, lpvBuffer, (CONST LPMAT2)lpmat2, TRUE); + return IntGetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, FALSE); } /* - * @unimplemented + * @implemented */ -DWORD -WINAPI +DWORD WINAPI GetGlyphOutlineWow( - DWORD a0, - DWORD a1, - DWORD a2, - DWORD a3, - DWORD a4, - DWORD a5, - DWORD a6 -) + _In_ HDC hdc, + _In_ UINT uChar, + _In_ UINT fuFormat, + _Out_ LPGLYPHMETRICS lpgm, + _In_ DWORD cbBuffer, + _Out_writes_bytes_opt_(cbBuffer) LPVOID lpvBuffer, + _In_ CONST MAT2 *lpmat2) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + return IntGetGlyphOutlineA(hdc, uChar, fuFormat, lpgm, cbBuffer, lpvBuffer, lpmat2, TRUE); } /*