[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