[PATCH 08/12] gdi32: Change compute_gm_abc_metrics() position for consistent metrics value computation.

Byeongsik Jeon bsjeon at hanmail.net
Tue Jan 29 03:12:32 CST 2019


This patch reflects the metrics changes in the subpixel rendering.
The problem that arises from this patch is corrected in the following patches.
I will correct the problem and remove the todo_wine again.

Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
 dlls/gdi32/freetype.c   | 156 +++++++++++++++++++++-------------------
 dlls/gdi32/tests/font.c |   7 ++
 2 files changed, 89 insertions(+), 74 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index d0480333ce..02f7455619 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -6884,23 +6884,18 @@ static FT_Vector get_advance_metric(GdiFont *incoming_font, GdiFont *font,
     return adv;
 }
 
-static FT_BBox compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font,
-                                       const FT_Glyph_Metrics *metrics,
-                                       BOOL tategaki, BOOL vertical_metrics, BOOL needsTransform,
-                                       const FT_Matrix *transMat,
-                                       const FT_Matrix *transMatTategaki,
-                                       const FT_Matrix *transMatUnrotated,
-                                       GLYPHMETRICS *gm, ABC *abc )
+static void compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font,
+                                    FT_BBox bbox, const FT_Glyph_Metrics *metrics,
+                                    BOOL tategaki, BOOL vertical_metrics, BOOL needsTransform,
+                                    const FT_Matrix *transMat,
+                                    const FT_Matrix *transMatTategaki,
+                                    const FT_Matrix *transMatUnrotated,
+                                    GLYPHMETRICS *gm, ABC *abc )
 {
-    FT_BBox bbox = { 0, 0, 0, 0 };
     FT_Vector adv, vec, origin;
 
     if (!needsTransform)
     {
-        bbox.xMin = (metrics->horiBearingX) & -64;
-        bbox.xMax = (metrics->horiBearingX + metrics->width + 63) & -64;
-        bbox.yMax = (metrics->horiBearingY + 63) & -64;
-        bbox.yMin = (metrics->horiBearingY - metrics->height) & -64;
         adv = get_advance_metric( incoming_font, font, metrics, NULL, vertical_metrics );
         gm->gmCellIncX = adv.x >> 6;
         gm->gmCellIncY = 0;
@@ -6911,37 +6906,8 @@ static FT_BBox compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font,
     }
     else
     {
-        INT xc, yc;
         FT_Pos lsb;
 
-        for (xc = 0; xc < 2; xc++)
-        {
-            for (yc = 0; yc < 2; yc++)
-            {
-                vec.x = metrics->horiBearingX + xc * metrics->width;
-                vec.y = metrics->horiBearingY - yc * metrics->height;
-                TRACE( "Vec %ld,%ld\n", vec.x, vec.y );
-                pFT_Vector_Transform( &vec, transMatTategaki );
-                if (xc == 0 && yc == 0)
-                {
-                    bbox.xMin = bbox.xMax = vec.x;
-                    bbox.yMin = bbox.yMax = vec.y;
-                }
-                else
-                {
-                    if      (vec.x < bbox.xMin) bbox.xMin = vec.x;
-                    else if (vec.x > bbox.xMax) bbox.xMax = vec.x;
-                    if      (vec.y < bbox.yMin) bbox.yMin = vec.y;
-                    else if (vec.y > bbox.yMax) bbox.yMax = vec.y;
-                }
-            }
-        }
-        bbox.xMin = bbox.xMin & -64;
-        bbox.xMax = (bbox.xMax + 63) & -64;
-        bbox.yMax = (bbox.yMax + 63) & -64;
-        bbox.yMin = bbox.yMin & -64;
-        TRACE( "transformed box: (%ld,%ld - %ld,%ld)\n", bbox.xMin, bbox.yMax, bbox.xMax, bbox.yMin );
-
         if (tategaki && (font->potm || get_outline_text_metrics( font )))
         {
             if (vertical_metrics)
@@ -6997,6 +6963,53 @@ static FT_BBox compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font,
     TRACE( "gm: %u,%u,%s,%d,%d\n", gm->gmBlackBoxX, gm->gmBlackBoxY,
            wine_dbgstr_point(&gm->gmptGlyphOrigin), gm->gmCellIncX, gm->gmCellIncY );
     TRACE( "abc: %d,%u,%d\n", abc->abcA, abc->abcB, abc->abcC );
+}
+
+static FT_BBox get_transformed_bbox( const FT_Glyph_Metrics *metrics,
+                                     BOOL needsTransform, const FT_Matrix *transMatTategaki )
+{
+    FT_BBox bbox = { 0, 0, 0, 0 };
+
+    if (!needsTransform)
+    {
+        bbox.xMin = (metrics->horiBearingX) & -64;
+        bbox.xMax = (metrics->horiBearingX + metrics->width + 63) & -64;
+        bbox.yMax = (metrics->horiBearingY + 63) & -64;
+        bbox.yMin = (metrics->horiBearingY - metrics->height) & -64;
+    }
+    else
+    {
+        FT_Vector vec;
+        INT xc, yc;
+
+        for (xc = 0; xc < 2; xc++)
+        {
+            for (yc = 0; yc < 2; yc++)
+            {
+                vec.x = metrics->horiBearingX + xc * metrics->width;
+                vec.y = metrics->horiBearingY - yc * metrics->height;
+                TRACE( "Vec %ld,%ld\n", vec.x, vec.y );
+                pFT_Vector_Transform( &vec, transMatTategaki );
+                if (xc == 0 && yc == 0)
+                {
+                    bbox.xMin = bbox.xMax = vec.x;
+                    bbox.yMin = bbox.yMax = vec.y;
+                }
+                else
+                {
+                    if      (vec.x < bbox.xMin) bbox.xMin = vec.x;
+                    else if (vec.x > bbox.xMax) bbox.xMax = vec.x;
+                    if      (vec.y < bbox.yMin) bbox.yMin = vec.y;
+                    else if (vec.y > bbox.yMax) bbox.yMax = vec.y;
+                }
+            }
+        }
+        bbox.xMin = bbox.xMin & -64;
+        bbox.xMax = (bbox.xMax + 63) & -64;
+        bbox.yMax = (bbox.yMax + 63) & -64;
+        bbox.yMin = bbox.yMin & -64;
+        TRACE( "transformed box: (%ld,%ld - %ld,%ld)\n", bbox.xMin, bbox.yMax, bbox.xMax, bbox.yMin );
+    }
 
     return bbox;
 }
@@ -7198,12 +7211,12 @@ static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int b
     return needed;
 }
 
-static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBox bbox, GLYPHMETRICS *gm,
+static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBox *bbox,
                                          BOOL needsTransform, FT_Matrix *transMatTategaki,
                                          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;
     FT_Outline *outline = &glyph->outline;
     FT_Bitmap ft_bitmap;
     DWORD max_level, pitch, needed = 0;
@@ -7226,7 +7239,7 @@ static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBo
 
             if (needsTransform)
                 pFT_Outline_Transform( outline, transMatTategaki );
-            pFT_Outline_Translate( outline, -bbox.xMin, -bbox.yMin );
+            pFT_Outline_Translate( outline, -bbox->xMin, -bbox->yMin );
 
             /* Note: FreeType will only set 'black' bits for us. */
             memset( buf, 0, needed );
@@ -7252,7 +7265,7 @@ static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBo
 
             if (needsTransform)
                 pFT_Outline_Transform( outline, transMatTategaki );
-            pFT_Outline_Translate( outline, -bbox.xMin, -bbox.yMin );
+            pFT_Outline_Translate( outline, -bbox->xMin, -bbox->yMin );
 
             memset( ft_bitmap.buffer, 0, buflen );
             pFT_Outline_Get_Bitmap( library, outline, &ft_bitmap );
@@ -7296,19 +7309,17 @@ static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBo
 
             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;
 
@@ -7336,7 +7347,7 @@ static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBo
             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;
@@ -7348,7 +7359,7 @@ static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBo
                 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;
@@ -7660,20 +7671,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
         /* metrics.width = min( metrics.width, ptm->tmMaxCharWidth << 6 ); */
     }
 
-    bbox = compute_gm_abc_metrics( incoming_font, font, &metrics,
-                                   tategaki, vertical_metrics, needsTransform,
-                                   &transMat, &transMatTategaki, &transMatUnrotated,
-                                   &gm, abc );
-
-    if ((ggo_metrics || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
-        is_identity_MAT2(lpmat)) /* don't cache custom transforms */
-        cache_gm_abc_metrics( font, glyph_index, &gm, abc );
-
-    if (ggo_metrics)
-    {
-        *lpgm = gm;
-        return 1; /* FIXME */
-    }
+    bbox = get_transformed_bbox( &metrics, needsTransform, &transMatTategaki );
 
     switch (ft_face->glyph->format)
     {
@@ -7682,7 +7680,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
                                                 buflen, buf );
             break;
         case FT_GLYPH_FORMAT_OUTLINE:
-            needed = get_ggo_glyph_from_outline( ft_face->glyph, format, bbox, &gm,
+            needed = get_ggo_glyph_from_outline( ft_face->glyph, format, &bbox,
                                                  needsTransform, &transMatTategaki,
                                                  buflen, buf );
             break;
@@ -7690,10 +7688,20 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
             FIXME("loaded glyph format %x\n", ft_face->glyph->format);
             return GDI_ERROR;
     }
-    if (needed == GDI_ERROR) return GDI_ERROR;
 
-    *lpgm = gm;
-    return needed;
+    compute_gm_abc_metrics( incoming_font, font, bbox, &metrics,
+                            tategaki, vertical_metrics, needsTransform,
+                            &transMat, &transMatTategaki, &transMatUnrotated,
+                            &gm, abc );
+
+    if ((ggo_metrics || format == GGO_BITMAP || format ==  WINE_GGO_GRAY16_BITMAP) &&
+        is_identity_MAT2(lpmat)) /* don't cache custom transforms */
+        cache_gm_abc_metrics( font, glyph_index, &gm, abc );
+
+    if (ggo_metrics || needed != GDI_ERROR)
+        *lpgm = gm;
+
+    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 67e8941b5e..f8762eca56 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);
@@ -6134,8 +6139,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