[PATCH 3/6] gdi32: Add a helper function to get a more accurate transformed outline bbox.

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


Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
For example, the rotation of 'O', the slant of 'V'.

get_transformed_bitmap() implementation will be posted separately:
WINFNT bitmap transform(scale, slant, ...).

 dlls/gdi32/freetype.c | 73 ++++++++++++++++++++++++++-----------------
 1 file changed, 44 insertions(+), 29 deletions(-)

diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index d099f6cb44..1f1957f2ca 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -6992,8 +6992,30 @@ static void compute_metrics( GdiFont *incoming_font, GdiFont *font,
 
 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
 
-static DWORD get_mono_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox,
-                                    BOOL fake_bold, BOOL needs_transform, FT_Matrix matrices[3],
+static FT_BBox get_transformed_outline( FT_Outline *outline, FT_BBox bbox,
+                                        BOOL needs_transform, const FT_Matrix matrices[3] )
+{
+    FT_BBox cbox;
+
+    if (needs_transform)
+        pFT_Outline_Transform( outline, &matrices[matrix_vert] );
+    pFT_Outline_Get_CBox( outline, &cbox );
+
+    /* Respect the poorly created fonts metrics fixing. */
+    bbox.xMin = max( bbox.xMin, cbox.xMin );
+    bbox.xMax = min( bbox.xMax, cbox.xMax );
+    bbox.yMin = max( bbox.yMin, cbox.yMin );
+    bbox.yMax = min( bbox.yMax, cbox.yMax );
+
+    bbox.xMin = bbox.xMin & -64;
+    bbox.xMax = (bbox.xMax + 63) & -64;
+    bbox.yMax = (bbox.yMax + 63) & -64;
+    bbox.yMin = bbox.yMin & -64;
+
+    return bbox;
+}
+
+static DWORD get_mono_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, BOOL fake_bold,
                                     DWORD buflen, BYTE *buf )
 {
     DWORD width  = (bbox.xMax - bbox.xMin ) >> 6;
@@ -7041,12 +7063,9 @@ static DWORD get_mono_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox,
         ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
         ft_bitmap.buffer = buf;
 
-        if (needs_transform)
-            pFT_Outline_Transform( &glyph->outline, &matrices[matrix_vert] );
-        pFT_Outline_Translate( &glyph->outline, -bbox.xMin, -bbox.yMin );
-
         /* Note: FreeType will only set 'black' bits for us. */
         memset( buf, 0, buflen );
+        pFT_Outline_Translate( &glyph->outline, -bbox.xMin, -bbox.yMin );
         pFT_Outline_Get_Bitmap( library, &glyph->outline, &ft_bitmap );
         break;
 
@@ -7059,8 +7078,7 @@ static DWORD get_mono_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox,
 }
 
 static DWORD get_antialias_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT format,
-                                         BOOL fake_bold, BOOL needs_transform, FT_Matrix matrices[3],
-                                         DWORD buflen, BYTE *buf )
+                                         BOOL fake_bold, DWORD buflen, BYTE *buf )
 {
     DWORD width  = (bbox.xMax - bbox.xMin ) >> 6;
     DWORD height = (bbox.yMax - bbox.yMin ) >> 6;
@@ -7107,11 +7125,8 @@ static DWORD get_antialias_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT
         ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
         ft_bitmap.buffer = buf;
 
-        if (needs_transform)
-            pFT_Outline_Transform( &glyph->outline, &matrices[matrix_vert] );
-        pFT_Outline_Translate( &glyph->outline, -bbox.xMin, -bbox.yMin );
-
         memset( buf, 0, buflen );
+        pFT_Outline_Translate( &glyph->outline, -bbox.xMin, -bbox.yMin );
         pFT_Outline_Get_Bitmap( library, &glyph->outline, &ft_bitmap );
 
         if (max_level != 255)
@@ -7137,8 +7152,7 @@ static DWORD get_antialias_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox bbox, UINT
 }
 
 static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox *bbox, UINT format,
-                                        BOOL fake_bold, BOOL needs_transform, FT_Matrix matrices[3],
-                                        DWORD buflen, BYTE *buf )
+                                        BOOL fake_bold, DWORD buflen, BYTE *buf )
 {
     DWORD width  = (bbox->xMax - bbox->xMin ) >> 6;
     DWORD height = (bbox->yMax - bbox->yMin ) >> 6;
@@ -7213,9 +7227,6 @@ static DWORD get_subpixel_glyph_bitmap( FT_GlyphSlot glyph, FT_BBox *bbox, UINT
         if (!buf || !buflen) return needed;
         if (needed > buflen) return GDI_ERROR;
 
-        if (needs_transform)
-            pFT_Outline_Transform( &glyph->outline, &matrices[matrix_vert] );
-
 #ifdef FT_LCD_FILTER_H
         if (pFT_Library_SetLcdFilter)
             pFT_Library_SetLcdFilter( library, FT_LCD_FILTER_DEFAULT );
@@ -7612,11 +7623,23 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
 	return GDI_ERROR;
     }
 
+    switch (ft_face->glyph->format)
+    {
+    case FT_GLYPH_FORMAT_OUTLINE:
+        bbox = get_transformed_outline( &ft_face->glyph->outline, bbox, needsTransform, matrices );
+        break;
+    case FT_GLYPH_FORMAT_BITMAP:
+        /* TODO: winfnt, embedded bitmap transform(scale, slant, ...). */
+        break;
+    default:
+        FIXME( "loaded glyph format %x\n", ft_face->glyph->format );
+        return GDI_ERROR;
+    }
+
     switch (format)
     {
     case GGO_BITMAP:
-        needed = get_mono_glyph_bitmap( ft_face->glyph, bbox, font->fake_bold,
-                                        needsTransform, matrices, buflen, buf );
+        needed = get_mono_glyph_bitmap( ft_face->glyph, bbox, font->fake_bold, buflen, buf );
         break;
 
     case GGO_GRAY2_BITMAP:
@@ -7624,7 +7647,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
     case GGO_GRAY8_BITMAP:
     case WINE_GGO_GRAY16_BITMAP:
         needed = get_antialias_glyph_bitmap( ft_face->glyph, bbox, format, font->fake_bold,
-                                             needsTransform, matrices, buflen, buf );
+                                             buflen, buf );
 	break;
 
     case WINE_GGO_HRGB_BITMAP:
@@ -7632,7 +7655,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
     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, buflen, buf );
+                                            buflen, buf );
         break;
 
     case GGO_NATIVE:
@@ -7640,10 +7663,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
         FT_Outline *outline = &ft_face->glyph->outline;
 
         if(buflen == 0) buf = NULL;
-
-        if (needsTransform && buf)
-            pFT_Outline_Transform( outline, &matrices[matrix_vert] );
-
         needed = get_native_glyph_outline(outline, buflen, NULL);
 
         if (!buf || !buflen)
@@ -7658,10 +7677,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
       {
         FT_Outline *outline = &ft_face->glyph->outline;
         if(buflen == 0) buf = NULL;
-
-        if (needsTransform && buf)
-            pFT_Outline_Transform( outline, &matrices[matrix_vert] );
-
         needed = get_bezier_glyph_outline(outline, buflen, NULL);
 
         if (!buf || !buflen)
-- 
2.20.1




More information about the wine-devel mailing list