[PATCH 3/3] dwrite: Implement grayscale rendering mode

Nikolay Sivov nsivov at codeweavers.com
Thu Aug 27 00:39:45 CDT 2015


---

-------------- next part --------------
>From d38f365d7f0eaca1055ecab48beb184285438202 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Thu, 27 Aug 2015 08:36:58 +0300
Subject: [PATCH 3/3] dwrite: Implement grayscale rendering mode

---
 dlls/dwrite/dwrite_private.h |   3 +-
 dlls/dwrite/font.c           |  41 +++++++++----
 dlls/dwrite/freetype.c       | 136 +++++++++++++++++++++++++++++++------------
 3 files changed, 129 insertions(+), 51 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 39043d9..a7b8c46 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -199,6 +199,7 @@ struct dwrite_glyphbitmap {
     INT pitch;
     RECT bbox;
     BYTE *buf;
+    DWRITE_TEXTURE_TYPE type;
 };
 
 extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
@@ -212,7 +213,7 @@ extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32,INT) DECLSPEC_HID
 extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN;
 extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT16) DECLSPEC_HIDDEN;
 extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
-extern void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
+extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
 extern INT freetype_get_charmap_index(IDWriteFontFace2*,BOOL*) DECLSPEC_HIDDEN;
 extern INT32 freetype_get_glyph_advance(IDWriteFontFace2*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN;
 
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index f66d49c..1b9b6a2 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -3622,6 +3622,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
     glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip;
     glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL ||
         analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
+    glyph_bitmap.type = type;
     bbox = &glyph_bitmap.bbox;
 
     for (i = 0; i < analysis->run.glyphCount; i++) {
@@ -3629,6 +3630,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
         FLOAT advance = analysis->advances[i];
         int x, y, width, height;
         BYTE *src, *dst;
+        BOOL is_1bpp;
 
         glyph_bitmap.index = analysis->run.glyphIndices[i];
         freetype_get_glyph_bbox(&glyph_bitmap);
@@ -3640,10 +3642,14 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
 
         width = bbox->right - bbox->left;
         height = bbox->bottom - bbox->top;
-        glyph_bitmap.pitch = ((width + 31) >> 5) << 2;
+
+        if (type == DWRITE_TEXTURE_CLEARTYPE_3x1)
+            glyph_bitmap.pitch = (width + 3) / 4 * 4;
+        else
+            glyph_bitmap.pitch = ((width + 31) >> 5) << 2;
 
         glyph_bitmap.buf = src = heap_alloc_zero(height * glyph_bitmap.pitch);
-        freetype_get_glyph_bitmap(&glyph_bitmap);
+        is_1bpp = freetype_get_glyph_bitmap(&glyph_bitmap);
 
         if (is_rtl)
             OffsetRect(bbox, origin_x - advance, 0);
@@ -3658,21 +3664,32 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
         /* blit to analysis bitmap */
         dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds);
 
-        /* convert 1bpp to 8bpp/24bpp */
-        if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) {
-            for (y = 0; y < height; y++) {
-                for (x = 0; x < width; x++)
-                    dst[3*x] = dst[3*x+1] = dst[3*x+2] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0;
-                src += get_dib_stride(width, 1);
-                dst += (analysis->bounds.right - analysis->bounds.left) * 3;
+        if (is_1bpp) {
+            /* convert 1bpp to 8bpp/24bpp */
+            if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) {
+                for (y = 0; y < height; y++) {
+                    for (x = 0; x < width; x++)
+                        dst[3*x] = dst[3*x+1] = dst[3*x+2] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0;
+                    src += glyph_bitmap.pitch;
+                    dst += (analysis->bounds.right - analysis->bounds.left) * 3;
+                }
+            }
+            else {
+                for (y = 0; y < height; y++) {
+                    for (x = 0; x < width; x++)
+                        dst[x] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0;
+                    src += get_dib_stride(width, 1);
+                    dst += analysis->bounds.right - analysis->bounds.left;
+                }
             }
         }
         else {
+            /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
             for (y = 0; y < height; y++) {
                 for (x = 0; x < width; x++)
-                    dst[x] = (src[x / 8] & masks[x % 8]) ? DWRITE_ALPHA_MAX : 0;
-                src += get_dib_stride(width, 1);
-                dst += analysis->bounds.right - analysis->bounds.left;
+                    dst[3*x] = dst[3*x+1] = dst[3*x+2] = src[x];
+                src += glyph_bitmap.pitch;
+                dst += (analysis->bounds.right - analysis->bounds.left) * 3;
             }
         }
 
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index 1f7e6a9..d10f370 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -510,10 +510,101 @@ void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
     bitmap->bbox.bottom = -bbox.yMin;
 }
 
-void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
+static BOOL freetype_get_aliased_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph)
 {
     const RECT *bbox = &bitmap->bbox;
+    int width = bbox->right - bbox->left;
+    int height = bbox->bottom - bbox->top;
+
+    if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+        FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
+        const FT_Outline *src = &outline->outline;
+        FT_Bitmap ft_bitmap;
+        FT_Outline copy;
+
+        ft_bitmap.width = width;
+        ft_bitmap.rows = height;
+        ft_bitmap.pitch = bitmap->pitch;
+        ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+        ft_bitmap.buffer = bitmap->buf;
+
+        /* Note: FreeType will only set 'black' bits for us. */
+        if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) {
+            pFT_Outline_Copy(src, &copy);
+            pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
+            pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
+            pFT_Outline_Done(library, &copy);
+        }
+    }
+    else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+        FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
+        BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf;
+        int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3);
+        int h = min(height, ft_bitmap->rows);
+
+        while (h--) {
+            memcpy(dst, src, w);
+            src += ft_bitmap->pitch;
+            dst += bitmap->pitch;
+        }
+    }
+    else
+        FIXME("format %x not handled\n", glyph->format);
+
+    return TRUE;
+}
+
+static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_Glyph glyph)
+{
+    const RECT *bbox = &bitmap->bbox;
+    int width = bbox->right - bbox->left;
+    int height = bbox->bottom - bbox->top;
+    BOOL ret = FALSE;
+
+    if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+        FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
+        const FT_Outline *src = &outline->outline;
+        FT_Bitmap ft_bitmap;
+        FT_Outline copy;
+
+        ft_bitmap.width = width;
+        ft_bitmap.rows = height;
+        ft_bitmap.pitch = bitmap->pitch;
+        ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
+        ft_bitmap.buffer = bitmap->buf;
+
+        /* Note: FreeType will only set 'black' bits for us. */
+        if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) {
+            pFT_Outline_Copy(src, &copy);
+            pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
+            pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
+            pFT_Outline_Done(library, &copy);
+        }
+    }
+    else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+        FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
+        BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf;
+        int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3);
+        int h = min(height, ft_bitmap->rows);
+
+        while (h--) {
+            memcpy(dst, src, w);
+            src += ft_bitmap->pitch;
+            dst += bitmap->pitch;
+        }
+
+        ret = TRUE;
+    }
+    else
+        FIXME("format %x not handled\n", glyph->format);
+
+    return ret;
+}
+
+BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
+{
     FTC_ImageTypeRec imagetype;
+    BOOL ret = FALSE;
     FT_Glyph glyph;
 
     imagetype.face_id = bitmap->fontface;
@@ -523,45 +614,14 @@ void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
 
     EnterCriticalSection(&freetype_cs);
     if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) {
-        int width = bbox->right - bbox->left;
-        int height = bbox->bottom - bbox->top;
-
-        if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
-            FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
-            const FT_Outline *src = &outline->outline;
-            FT_Bitmap ft_bitmap;
-            FT_Outline copy;
-
-            ft_bitmap.width = width;
-            ft_bitmap.rows = height;
-            ft_bitmap.pitch = bitmap->pitch;
-            ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
-            ft_bitmap.buffer = bitmap->buf;
-
-            /* Note: FreeType will only set 'black' bits for us. */
-            if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) {
-                pFT_Outline_Copy(src, &copy);
-                pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6);
-                pFT_Outline_Get_Bitmap(library, &copy, &ft_bitmap);
-                pFT_Outline_Done(library, &copy);
-            }
-        }
-        else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
-            FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
-            BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf;
-            int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3);
-            int h = min(height, ft_bitmap->rows);
-
-            while (h--) {
-                memcpy(dst, src, w);
-                src += ft_bitmap->pitch;
-                dst += bitmap->pitch;
-            }
-        }
+        if (bitmap->type == DWRITE_TEXTURE_CLEARTYPE_3x1)
+            ret = freetype_get_aa_glyph_bitmap(bitmap, glyph);
         else
-            FIXME("format %x not handled\n", glyph->format);
+            ret = freetype_get_aliased_glyph_bitmap(bitmap, glyph);
     }
     LeaveCriticalSection(&freetype_cs);
+
+    return ret;
 }
 
 INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)
@@ -675,7 +735,7 @@ void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
     memset(&bitmap->bbox, 0, sizeof(bitmap->bbox));
 }
 
-void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
+BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
 {
 }
 
-- 
2.1.4



More information about the wine-patches mailing list