From 88acc9c899f20c3ba92353b7933f0a9f64bed3b0 Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Fri, 4 Oct 2013 00:56:17 +0900 Subject: [PATCH] gdi32: Don't modify output glyph metrics unless the function succeeds. --- dlls/gdi32/freetype.c | 53 ++++++++++++++++++++++------------------- dlls/gdi32/tests/font.c | 5 ++++ 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index ca9e18f9be9..ab7b99fbbd0 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6184,6 +6184,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, const MAT2* lpmat) { static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)}; + GLYPHMETRICS gm; FT_Face ft_face = incoming_font->ft_face; GdiFont *font = incoming_font; FT_Glyph_Metrics metrics; @@ -6419,8 +6420,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, top = (metrics.horiBearingY + 63) & -64; bottom = (metrics.horiBearingY - metrics.height) & -64; - lpgm->gmCellIncX = adv; - lpgm->gmCellIncY = 0; + gm.gmCellIncX = adv; + gm.gmCellIncY = 0; origin_x = left; origin_y = top; } else { @@ -6492,14 +6493,14 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, vec.x = metrics.horiAdvance; vec.y = 0; pFT_Vector_Transform(&vec, &transMat); - lpgm->gmCellIncY = -((vec.y+63) >> 6); + gm.gmCellIncY = -((vec.y+63) >> 6); if (!avgAdvance || vec.y) - lpgm->gmCellIncX = (vec.x+63) >> 6; + gm.gmCellIncX = (vec.x+63) >> 6; else { vec.x = incoming_font->ntmAvgWidth; vec.y = 0; pFT_Vector_Transform(&vec, &transMat); - lpgm->gmCellIncX = pFT_MulFix(vec.x, em_scale) * 2; + gm.gmCellIncX = pFT_MulFix(vec.x, em_scale) * 2; } if (vertical_metrics) @@ -6520,28 +6521,29 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, width = (right - left) >> 6; height = (top - bottom) >> 6; - lpgm->gmBlackBoxX = width ? width : 1; - lpgm->gmBlackBoxY = height ? height : 1; - lpgm->gmptGlyphOrigin.x = origin_x >> 6; - lpgm->gmptGlyphOrigin.y = origin_y >> 6; + gm.gmBlackBoxX = width ? width : 1; + gm.gmBlackBoxY = height ? height : 1; + gm.gmptGlyphOrigin.x = origin_x >> 6; + gm.gmptGlyphOrigin.y = origin_y >> 6; abc->abcA = left >> 6; - abc->abcB = lpgm->gmBlackBoxX; + abc->abcB = gm.gmBlackBoxX; abc->abcC = adv - abc->abcA - abc->abcB; - TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY, - wine_dbgstr_point(&lpgm->gmptGlyphOrigin), - lpgm->gmCellIncX, lpgm->gmCellIncY); + TRACE("%u,%u,%s,%d,%d\n", gm.gmBlackBoxX, gm.gmBlackBoxY, + wine_dbgstr_point(&gm.gmptGlyphOrigin), + gm.gmCellIncX, gm.gmCellIncY); if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && is_identity_MAT2(lpmat)) /* don't cache custom transforms */ { - FONT_GM(font,original_index)->gm = *lpgm; + FONT_GM(font,original_index)->gm = gm; FONT_GM(font,original_index)->abc = *abc; FONT_GM(font,original_index)->init = TRUE; } if(format == GGO_METRICS) { + *lpgm = gm; return 1; /* FIXME */ } @@ -6626,7 +6628,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, src += ft_face->glyph->bitmap.pitch; dst += pitch; } - return needed; + break; } case ft_glyph_format_outline: { @@ -6654,7 +6656,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, start += pitch; } } - return needed; + break; } default: @@ -6717,7 +6719,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, if (!width || !height) { - if (!buf || !buflen) return 0; + if (!buf || !buflen) break; return GDI_ERROR; } @@ -6725,18 +6727,18 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, { if ( render_mode == FT_RENDER_MODE_LCD) { - lpgm->gmBlackBoxX += 2; - lpgm->gmptGlyphOrigin.x -= 1; + gm.gmBlackBoxX += 2; + gm.gmptGlyphOrigin.x -= 1; } else { - lpgm->gmBlackBoxY += 2; - lpgm->gmptGlyphOrigin.y += 1; + gm.gmBlackBoxY += 2; + gm.gmptGlyphOrigin.y += 1; } } - width = lpgm->gmBlackBoxX; - height = lpgm->gmBlackBoxY; + width = gm.gmBlackBoxX; + height = gm.gmBlackBoxY; pitch = width * 4; needed = pitch * height; @@ -6771,7 +6773,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, vmul = 3; } - x_shift = ft_face->glyph->bitmap_left - lpgm->gmptGlyphOrigin.x; + x_shift = ft_face->glyph->bitmap_left - gm.gmptGlyphOrigin.x; if ( x_shift < 0 ) { src += hmul * -x_shift; @@ -6783,7 +6785,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, width -= x_shift; } - y_shift = lpgm->gmptGlyphOrigin.y - ft_face->glyph->bitmap_top; + y_shift = gm.gmptGlyphOrigin.y - ft_face->glyph->bitmap_top; if ( y_shift < 0 ) { src += src_pitch * vmul * -y_shift; @@ -7025,6 +7027,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, FIXME("Unsupported format %d\n", format); return GDI_ERROR; } + *lpgm = gm; return needed; } diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 031b86aa295..2343db654e6 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -4172,7 +4172,12 @@ static void test_GetGlyphOutline(void) ok(gm.gmBlackBoxY == 1, "%2d:expected 1, got %u\n", fmt[i], gm.gmBlackBoxY); } else + { ok(ret == GDI_ERROR, "%2d:GetGlyphOutlineW should return GDI_ERROR, got %d\n", fmt[i], ret); + memset(&gm2, 0xab, sizeof(gm2)); + ok(memcmp(&gm, &gm2, sizeof(GLYPHMETRICS)) == 0, + "%2d:GLYPHMETRICS shouldn't be touched on error\n", fmt[i]); + } } }