[PATCH 2/6] gdi32: Change the compute_metrics() location to get more accurate metrics.

Byeongsik Jeon bsjeon at hanmail.net
Mon Feb 11 02:20:17 CST 2019


Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
This patch reflects the metrics changes in the subpixel rendering.
The problem that arises from this patch is corrected in the following patches.

match_off_by_n(abcw[0].abcB, abc[0].abcB, 2):
Because the metric value added by the current Wine subpixel rendering is
roughly enough value, the abcB will be up to 2 pixels different.

Even if I calculate with bitmap data rendered by FreeType, there are many
cases where 2 pixels difference is made. I think this is the limit from the
difference between FreeType and Windows GDI.


 dlls/gdi32/freetype.c   | 56 ++++++++++++++++++-----------------------
 dlls/gdi32/tests/font.c |  7 ++++++
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index f5c292235e..d099f6cb44 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -7136,12 +7136,12 @@ static DWORD get_antialias_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT
     return needed;
 }
 
-static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT format,
+static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox *bbox, UINT format,
                                         BOOL fake_bold, BOOL needs_transform, FT_Matrix matrices[3],
-                                        GLYPHMETRICS *gm, DWORD buflen, BYTE *buf )
+                                        DWORD buflen, BYTE *buf )
 {
-    DWORD width  = (bbox.xMax - bbox.xMin ) >> 6;
-    DWORD height = (bbox.yMax - bbox.yMin ) >> 6;
+    DWORD width  = (bbox->xMax - bbox->xMin ) >> 6;
+    DWORD height = (bbox->yMax - bbox->yMin ) >> 6;
     DWORD pitch, needed = 0;
     BYTE *src, *dst;
     INT  w, h, x;
@@ -7196,19 +7196,17 @@ static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT f
 
         if ( render_mode == FT_RENDER_MODE_LCD)
         {
-            gm->gmBlackBoxX += 2;
-            gm->gmptGlyphOrigin.x -= 1;
-            bbox.xMin -= (1 << 6);
+            bbox->xMin -= (1 << 6);
+            bbox->xMax += (1 << 6);
         }
         else
         {
-            gm->gmBlackBoxY += 2;
-            gm->gmptGlyphOrigin.y += 1;
-            bbox.yMax += (1 << 6);
+            bbox->yMax += (1 << 6);
+            bbox->yMin -= (1 << 6);
         }
 
-        width  = gm->gmBlackBoxX;
-        height = gm->gmBlackBoxY;
+        width  = (bbox->xMax - bbox->xMin ) >> 6;
+        height = (bbox->yMax - bbox->yMin ) >> 6;
         pitch  = width * 4;
         needed = pitch * height;
 
@@ -7237,7 +7235,7 @@ static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT f
         hmul       = render_mode == FT_RENDER_MODE_LCD ? 3 : 1;
         vmul       = render_mode == FT_RENDER_MODE_LCD ? 1 : 3;
 
-        x_shift = glyph->bitmap_left - (bbox.xMin >> 6);
+        x_shift = glyph->bitmap_left - (bbox->xMin >> 6);
         if ( x_shift < 0 )
         {
             src += hmul * -x_shift;
@@ -7249,7 +7247,7 @@ static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT f
             width -= x_shift;
         }
 
-        y_shift = (bbox.yMax >> 6) - glyph->bitmap_top;
+        y_shift = (bbox->yMax >> 6) - glyph->bitmap_top;
         if ( y_shift < 0 )
         {
             src += src_pitch * vmul * -y_shift;
@@ -7606,19 +7604,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
     }
 
     bbox = get_transformed_bbox( &metrics, needsTransform, matrices );
-    compute_metrics( incoming_font, font, bbox, &metrics,
-                     tategaki, vertical_metrics, needsTransform, matrices,
-                     &gm, abc );
-
-    if ((ggo_metrics || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
-        is_identity_MAT2(lpmat)) /* don't cache custom transforms */
-        set_cached_metrics( font, glyph_index, &gm, abc );
-
-    if (ggo_metrics)
-    {
-        *lpgm = gm;
-        return 1; /* FIXME */
-    }
 
     if(ft_face->glyph->format != ft_glyph_format_outline &&
        (format == GGO_NATIVE || format == GGO_BEZIER))
@@ -7646,8 +7631,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
     case WINE_GGO_HBGR_BITMAP:
     case WINE_GGO_VRGB_BITMAP:
     case WINE_GGO_VBGR_BITMAP:
-        needed = get_subpixel_glyph_bitmap( ft_face->glyph, bbox, format, font->fake_bold,
-                                            needsTransform, matrices, &gm, buflen, buf );
+        needed = get_subpixel_glyph_bitmap( ft_face->glyph, &bbox, format, font->fake_bold,
+                                            needsTransform, matrices, buflen, buf );
         break;
 
     case GGO_NATIVE:
@@ -7692,10 +7677,19 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
         FIXME("Unsupported format %d\n", format);
 	return GDI_ERROR;
     }
-    if (needed != GDI_ERROR)
+
+    compute_metrics( incoming_font, font, bbox, &metrics,
+                     tategaki, vertical_metrics, needsTransform, matrices,
+                     &gm, abc );
+
+    if ((ggo_metrics || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
+        is_identity_MAT2(lpmat)) /* don't cache custom transforms */
+        set_cached_metrics( font, glyph_index, &gm, abc );
+
+    if (ggo_metrics || needed != GDI_ERROR)
         *lpgm = gm;
 
-    return needed;
+    return ggo_metrics ? 1 : needed; /* FIXME: GGO_METRICS return value? */
 }
 
 static BOOL get_bitmap_text_metrics(GdiFont *font)
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 6e7ac1e8e5..53035cfb9b 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -1335,8 +1335,11 @@ static void test_GetCharABCWidths(void)
     /* 3) compare ABC results */
     ok(match_off_by_1(abcw[0].abcA, abc[0].abcA, FALSE),
        "got %d, expected %d (A)\n", abc[0].abcA, abcw[0].abcA);
+    todo_wine
     ok(match_off_by_1(abcw[0].abcB, abc[0].abcB, FALSE),
        "got %d, expected %d (B)\n", abc[0].abcB, abcw[0].abcB);
+    ok(match_off_by_n(abcw[0].abcB, abc[0].abcB, 2),
+       "got %d, expected %d (B)\n", abc[0].abcB, abcw[0].abcB);
     ok(match_off_by_1(abcw[0].abcC, abc[0].abcC, FALSE),
        "got %d, expected %d (C)\n", abc[0].abcC, abcw[0].abcC);
 
@@ -1382,9 +1385,11 @@ static void test_GetCharABCWidths(void)
             ret = GetCharABCWidthsA(hdc, code, code, abc);
             ok(ret, "GetCharABCWidthsA should have succeeded at width %d\n", i);
 
+            todo_wine
             ok(abc[0].abcA == gm.gmptGlyphOrigin.x,
                "abcA(%d) and gmptGlyphOrigin.x(%d) values are different at width %d\n",
                abc[0].abcA, gm.gmptGlyphOrigin.x, i);
+            todo_wine
             ok(abc[0].abcB == gm.gmBlackBoxX,
                "abcB(%d) and gmBlackBoxX(%d) values are different at width %d\n",
                abc[0].abcB, gm.gmBlackBoxX, i);
@@ -6135,8 +6140,10 @@ static void check_vertical_metrics(const char *face)
     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
     ret = GetCharABCWidthsW(hdc, code, code, &vabc);
     ok(ret, "GetCharABCWidthsW failed\n");
+    todo_wine
     ok(vabc.abcA == vgm.gmptGlyphOrigin.x, "expected %d, got %d\n",
        vabc.abcA, vgm.gmptGlyphOrigin.x);
+    todo_wine
     ok(vabc.abcB == vgm.gmBlackBoxX, "expected %d, got %d\n",
        vabc.abcB, vgm.gmBlackBoxX);
     ok(vabc.abcA + vabc.abcB + vabc.abcC == vgm.gmCellIncX,
-- 
2.20.1




More information about the wine-devel mailing list