Signed-off-by: Byeongsik Jeon bsjeon@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,