diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 4e271eaadec..205224bd8fe 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -2336,6 +2336,8 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat, DWORD ret; UINT c; + if (!lpmat2) return GDI_ERROR; + if(!(fuFormat & GGO_GLYPH_INDEX)) { int len; char mbchs[2]; @@ -2364,12 +2366,15 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 *lpmat2 ) { - DC *dc = get_dc_ptr(hdc); + DC *dc; DWORD ret; TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n", hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 ); + if (!lpmat2) return GDI_ERROR; + + dc = get_dc_ptr(hdc); if(!dc) return GDI_ERROR; if(dc->gdiFont) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 5c7b51bbf97..bad27053e0f 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -4417,7 +4417,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, font->gmsize * sizeof(GM*)); } else { if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL && - FONT_GM(font,original_index)->init && (!lpmat || is_identity_MAT2(lpmat))) + FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat)) { *lpgm = FONT_GM(font,original_index)->gm; TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY, @@ -4499,7 +4499,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, } /* Extra transformation specified by caller */ - if (lpmat && !is_identity_MAT2(lpmat)) + if (!is_identity_MAT2(lpmat)) { FT_Matrix extraMat; extraMat.xx = FT_FixedFromFIXED(lpmat->eM11); @@ -4588,7 +4588,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, lpgm->gmCellIncX, lpgm->gmCellIncY); if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && - (!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */ + is_identity_MAT2(lpmat)) /* don't cache custom transforms */ { FONT_GM(font,original_index)->gm = *lpgm; FONT_GM(font,original_index)->adv = adv; @@ -5600,6 +5600,7 @@ static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar, LPINT buffer) { + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; UINT c; GLYPHMETRICS gm; FT_UInt glyph_index; @@ -5612,7 +5613,7 @@ BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar, for(c = firstChar; c <= lastChar; c++) { get_glyph_index_linked(font, c, &linked_font, &glyph_index); WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, - &gm, 0, NULL, NULL); + &gm, 0, NULL, &identity); buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv; } LeaveCriticalSection( &freetype_cs ); @@ -5626,6 +5627,7 @@ BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar, BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar, LPABC buffer) { + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; UINT c; GLYPHMETRICS gm; FT_UInt glyph_index; @@ -5642,7 +5644,7 @@ BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar, for(c = firstChar; c <= lastChar; c++) { get_glyph_index_linked(font, c, &linked_font, &glyph_index); WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, - &gm, 0, NULL, NULL); + &gm, 0, NULL, &identity); buffer[c - firstChar].abcA = FONT_GM(linked_font,glyph_index)->lsb; buffer[c - firstChar].abcB = FONT_GM(linked_font,glyph_index)->bbx; buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb - @@ -5659,6 +5661,7 @@ BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar, BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD pgi, LPABC buffer) { + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; UINT c; GLYPHMETRICS gm; FT_UInt glyph_index; @@ -5674,7 +5677,7 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD if (!pgi) for(c = firstChar; c < firstChar+count; c++) { WineEngGetGlyphOutline(linked_font, c, GGO_METRICS | GGO_GLYPH_INDEX, - &gm, 0, NULL, NULL); + &gm, 0, NULL, &identity); buffer[c - firstChar].abcA = FONT_GM(linked_font,c)->lsb; buffer[c - firstChar].abcB = FONT_GM(linked_font,c)->bbx; buffer[c - firstChar].abcC = FONT_GM(linked_font,c)->adv - FONT_GM(linked_font,c)->lsb @@ -5683,7 +5686,7 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD else for(c = 0; c < count; c++) { WineEngGetGlyphOutline(linked_font, pgi[c], GGO_METRICS | GGO_GLYPH_INDEX, - &gm, 0, NULL, NULL); + &gm, 0, NULL, &identity); buffer[c].abcA = FONT_GM(linked_font,pgi[c])->lsb; buffer[c].abcB = FONT_GM(linked_font,pgi[c])->bbx; buffer[c].abcC = FONT_GM(linked_font,pgi[c])->adv @@ -5701,6 +5704,7 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count, INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size) { + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; INT idx; INT nfit = 0, ext; GLYPHMETRICS gm; @@ -5721,7 +5725,7 @@ BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count, for(idx = 0; idx < count; idx++) { get_glyph_index_linked(font, wstr[idx], &linked_font, &glyph_index); WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, - &gm, 0, NULL, NULL); + &gm, 0, NULL, &identity); size->cx += FONT_GM(linked_font,glyph_index)->adv; ext = size->cx; if (! pnfit || ext <= max_ext) { @@ -5746,6 +5750,7 @@ BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count, BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count, INT max_ext, LPINT pnfit, LPINT dxs, LPSIZE size) { + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} }; INT idx; INT nfit = 0, ext; GLYPHMETRICS gm; @@ -5763,7 +5768,7 @@ BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count, for(idx = 0; idx < count; idx++) { WineEngGetGlyphOutline(font, indices[idx], GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, - NULL); + &identity); size->cx += FONT_GM(font,indices[idx])->adv; ext = size->cx; if (! pnfit || ext <= max_ext) { diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 0aa9af66a37..38339ea3b88 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -2477,6 +2477,61 @@ static void test_orientation(void) DeleteDC(hdc); } +static void test_GetGlyphOutline(void) +{ + MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} }; + HDC hdc; + GLYPHMETRICS gm; + LOGFONTA lf; + HFONT hfont, old_hfont; + INT ret; + + if (!is_truetype_font_installed("Tahoma")) + { + skip("Tahoma is not installed\n"); + return; + } + + hdc = CreateCompatibleDC(0); + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = 72; + lstrcpyA(lf.lfFaceName, "Tahoma"); + SetLastError(0xdeadbeef); + hfont = CreateFontIndirectA(&lf); + ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError()); + old_hfont = SelectObject(hdc, hfont); + + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %u\n", GetLastError()); + + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL); + ok(ret == GDI_ERROR, "GetGlyphOutlineA should fail\n"); + ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError()); + + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + ok(ret != GDI_ERROR, "GetGlyphOutlineW error %u\n", GetLastError()); + + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineW(hdc, 'A', GGO_METRICS, &gm, 0, NULL, NULL); + if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + { + ok(ret == GDI_ERROR, "GetGlyphOutlineW should fail\n"); + ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError()); + } + + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + DeleteDC(hdc); +} + START_TEST(font) { init(); @@ -2514,4 +2569,5 @@ START_TEST(font) test_GetTextMetrics(); test_GdiRealizationInfo(); test_GetTextFace(); + test_GetGlyphOutline(); }