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