Alexandre Julliard : gdi32: Add a null driver fallback implementation for non-antialiased text output.

Alexandre Julliard julliard at winehq.org
Mon Nov 21 11:10:08 CST 2011


Module: wine
Branch: master
Commit: 5282ffadaddbfe858d50f57d6363d11a8dae8ad5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5282ffadaddbfe858d50f57d6363d11a8dae8ad5

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Nov 17 11:57:53 2011 +0100

gdi32: Add a null driver fallback implementation for non-antialiased text output.

---

 dlls/gdi32/driver.c      |    6 --
 dlls/gdi32/font.c        |  150 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/gdi32/gdi_private.h |    2 +
 3 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 9b951d0..0610347 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -301,12 +301,6 @@ static BOOL nulldrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UIN
     return TRUE;
 }
 
-static BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
-                                LPCWSTR str, UINT count, const INT *dx )
-{
-    return TRUE;
-}
-
 static BOOL nulldrv_FontIsLinked( PHYSDEV dev )
 {
     return FALSE;
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 97cc2b6..ee824f0 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -1607,6 +1607,156 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
 }
 
 
+/* helper for nulldrv_ExtTextOut */
+static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
+                               GLYPHMETRICS *metrics, struct gdi_image_bits *image )
+{
+    UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
+    static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
+    UINT indices[3] = {0, 0, 0x20};
+    int i;
+    DWORD ret, size;
+    int stride;
+
+    indices[0] = index;
+
+    for (i = 0; i < sizeof(indices) / sizeof(indices[0]); index = indices[++i])
+    {
+        ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
+        if (ret != GDI_ERROR) break;
+    }
+
+    if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
+    if (!image) return ERROR_SUCCESS;
+
+    image->ptr = NULL;
+    image->free = NULL;
+    if (!ret) return ERROR_SUCCESS; /* empty glyph */
+
+    stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
+    size = metrics->gmBlackBoxY * stride;
+
+    if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
+    image->is_copy = TRUE;
+    image->free = free_heap_bits;
+
+    ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
+    if (ret == GDI_ERROR)
+    {
+        HeapFree( GetProcessHeap(), 0, image->ptr );
+        return ERROR_NOT_FOUND;
+    }
+    return ERROR_SUCCESS;
+}
+
+/* helper for nulldrv_ExtTextOut */
+static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
+                        const struct gdi_image_bits *image, const RECT *clip )
+{
+    static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+    UINT x, y, i, count;
+    BYTE *ptr = image->ptr;
+    int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
+    POINT *pts;
+    RECT rect, clipped_rect;
+
+    rect.left   = origin_x  + metrics->gmptGlyphOrigin.x;
+    rect.top    = origin_y  - metrics->gmptGlyphOrigin.y;
+    rect.right  = rect.left + metrics->gmBlackBoxX;
+    rect.bottom = rect.top  + metrics->gmBlackBoxY;
+    if (!clip) clipped_rect = rect;
+    else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
+
+    pts = HeapAlloc( GetProcessHeap(), 0,
+                     max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
+    if (!pts) return;
+
+    count = 0;
+    ptr += (clipped_rect.top - rect.top) * stride;
+    for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
+    {
+        for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
+        {
+            while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
+            pts[count].x = rect.left + x;
+            while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
+            pts[count + 1].x = rect.left + x;
+            if (pts[count + 1].x > pts[count].x)
+            {
+                pts[count].y = pts[count + 1].y = y;
+                count += 2;
+            }
+        }
+    }
+    DPtoLP( hdc, pts, count );
+    for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
+    HeapFree( GetProcessHeap(), 0, pts );
+}
+
+/***********************************************************************
+ *           nulldrv_ExtTextOut
+ */
+BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
+                         LPCWSTR str, UINT count, const INT *dx )
+{
+    UINT i;
+    DWORD err;
+    HGDIOBJ orig;
+    HPEN pen;
+
+    if (flags & ETO_OPAQUE)
+    {
+        RECT rc = *rect;
+        HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
+
+        if (brush)
+        {
+            orig = SelectObject( dev->hdc, brush );
+            DPtoLP( dev->hdc, (POINT *)&rc, 2 );
+            PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
+            SelectObject( dev->hdc, orig );
+            DeleteObject( brush );
+        }
+    }
+
+    if (!count) return TRUE;
+
+    pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
+    orig = SelectObject( dev->hdc, pen );
+
+    for (i = 0; i < count; i++)
+    {
+        GLYPHMETRICS metrics;
+        struct gdi_image_bits image;
+
+        err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
+        if (err) continue;
+
+        if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
+        if (image.free) image.free( &image );
+
+        if (dx)
+        {
+            if (flags & ETO_PDY)
+            {
+                x += dx[ i * 2 ];
+                y += dx[ i * 2 + 1];
+            }
+            else x += dx[ i ];
+        }
+        else
+        {
+            x += metrics.gmCellIncX;
+            y += metrics.gmCellIncY;
+        }
+    }
+
+    SelectObject( dev->hdc, orig );
+    DeleteObject( pen );
+    return TRUE;
+}
+
+
 /***********************************************************************
  *           ExtTextOutA    (GDI32.@)
  *
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index c23a5cc..d8a793f 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -358,6 +358,8 @@ extern BOOL nulldrv_CopyBitmap( HBITMAP src, HBITMAP dst ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_EndPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern INT  nulldrv_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
 extern INT  nulldrv_ExtSelectClipRgn( PHYSDEV dev, HRGN rgn, INT mode ) DECLSPEC_HIDDEN;
+extern BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
+                                LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_FillRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_FlattenPath( PHYSDEV dev ) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list