Akihiro Sagawa : gdi32: Don' t modify output glyph metrics unless the function succeeds.
Alexandre Julliard
julliard at winehq.org
Thu Oct 3 15:18:02 CDT 2013
Module: wine
Branch: master
Commit: 88acc9c899f20c3ba92353b7933f0a9f64bed3b0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=88acc9c899f20c3ba92353b7933f0a9f64bed3b0
Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date: Fri Oct 4 00:56:17 2013 +0900
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 ca9e18f..ab7b99f 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 031b86a..2343db6 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]);
+ }
}
}
More information about the wine-cvs
mailing list