[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