Huw Davies : gdi32: Add support for 8 bpp dibs.

Alexandre Julliard julliard at winehq.org
Fri May 27 11:03:43 CDT 2011


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri May 27 14:26:02 2011 +0100

gdi32: Add support for 8 bpp dibs.

---

 dlls/gdi32/dibdrv/dc.c         |    4 +
 dlls/gdi32/dibdrv/dibdrv.h     |    1 +
 dlls/gdi32/dibdrv/primitives.c |  182 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+), 0 deletions(-)

diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index d6023b0..850fbc3 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -114,6 +114,10 @@ static BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD
             dib->funcs = &funcs_16;
         break;
 
+    case 8:
+        dib->funcs = &funcs_8;
+        break;
+
     default:
         TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count);
         return FALSE;
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index a330d0a..56d08b3 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -49,6 +49,7 @@ extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_32   DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_555  DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_16   DECLSPEC_HIDDEN;
+extern const primitive_funcs funcs_8    DECLSPEC_HIDDEN;
 extern const primitive_funcs funcs_null DECLSPEC_HIDDEN;
 
 extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c
index 8ff95fa..9622098 100644
--- a/dlls/gdi32/dibdrv/primitives.c
+++ b/dlls/gdi32/dibdrv/primitives.c
@@ -35,6 +35,11 @@ static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y)
     return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2);
 }
 
+static inline BYTE *get_pixel_ptr_8(const dib_info *dib, int x, int y)
+{
+    return (BYTE*)dib->bits + y * dib->stride + x;
+}
+
 static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor)
 {
     *ptr = (*ptr & and) ^ xor;
@@ -45,6 +50,11 @@ static inline void do_rop_16(WORD *ptr, WORD and, WORD xor)
     *ptr = (*ptr & and) ^ xor;
 }
 
+static inline void do_rop_8(BYTE *ptr, BYTE and, BYTE xor)
+{
+    *ptr = (*ptr & and) ^ xor;
+}
+
 static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
 {
     DWORD *ptr, *start;
@@ -73,6 +83,20 @@ static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD a
     }
 }
 
+static void solid_rects_8(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
+{
+    BYTE *ptr, *start;
+    int x, y, i;
+
+    for(i = 0; i < num; i++, rc++)
+    {
+        start = get_pixel_ptr_8(dib, rc->left, rc->top);
+        for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
+            for(x = rc->left, ptr = start; x < rc->right; x++)
+                do_rop_8(ptr++, and, xor);
+    }
+}
+
 static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor)
 {
     return;
@@ -194,6 +218,52 @@ static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const
     }
 }
 
+static void pattern_rects_8(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
+                            const dib_info *brush, void *and_bits, void *xor_bits)
+{
+    BYTE *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr;
+    int x, y, i;
+    POINT offset;
+
+    for(i = 0; i < num; i++, rc++)
+    {
+        offset = calc_brush_offset(rc, brush, origin);
+
+        start = get_pixel_ptr_8(dib, rc->left, rc->top);
+        start_and = (BYTE*)and_bits + offset.y * brush->stride;
+        start_xor = (BYTE*)xor_bits + offset.y * brush->stride;
+
+        for(y = rc->top; y < rc->bottom; y++, start += dib->stride)
+        {
+            and_ptr = start_and + offset.x;
+            xor_ptr = start_xor + offset.x;
+
+            for(x = rc->left, ptr = start; x < rc->right; x++)
+            {
+                do_rop_8(ptr++, *and_ptr++, *xor_ptr++);
+                if(and_ptr == start_and + brush->width)
+                {
+                    and_ptr = start_and;
+                    xor_ptr = start_xor;
+                }
+            }
+
+            offset.y++;
+            if(offset.y == brush->height)
+            {
+                start_and = and_bits;
+                start_xor = xor_bits;
+                offset.y = 0;
+            }
+            else
+            {
+                start_and += brush->stride;
+                start_xor += brush->stride;
+            }
+        }
+    }
+}
+
 static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
                                const dib_info *brush, void *and_bits, void *xor_bits)
 {
@@ -235,6 +305,37 @@ static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color)
     return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
 }
 
+static DWORD colorref_to_pixel_colortable(const dib_info *dib, COLORREF color)
+{
+    int i, best_index = 0;
+    RGBQUAD rgb;
+    DWORD diff, best_diff = 0xffffffff;
+
+    rgb.rgbRed = GetRValue(color);
+    rgb.rgbGreen = GetGValue(color);
+    rgb.rgbBlue = GetBValue(color);
+
+    for(i = 0; i < dib->color_table_size; i++)
+    {
+        RGBQUAD *cur = dib->color_table + i;
+        diff = (rgb.rgbRed - cur->rgbRed) * (rgb.rgbRed - cur->rgbRed)
+            +  (rgb.rgbGreen - cur->rgbGreen) * (rgb.rgbGreen - cur->rgbGreen)
+            +  (rgb.rgbBlue - cur->rgbBlue) * (rgb.rgbBlue - cur->rgbBlue);
+
+        if(diff == 0)
+        {
+            best_index = i;
+            break;
+        }
+
+        if(diff < best_diff)
+        {
+            best_diff = diff;
+            best_index = i;
+        }
+    }
+    return best_index;
+}
 
 static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
 {
@@ -524,6 +625,79 @@ static BOOL convert_to_16(dib_info *dst, const dib_info *src, const RECT *src_re
     return TRUE;
 }
 
+static BOOL convert_to_8(dib_info *dst, const dib_info *src, const RECT *src_rect)
+{
+    BYTE *dst_start = dst->bits, *dst_pixel;
+    INT x, y;
+    DWORD src_val;
+
+    switch(src->bit_count)
+    {
+    case 32:
+    {
+        DWORD *src_start = get_pixel_ptr_32(src, src_rect->left, src_rect->top), *src_pixel;
+
+        if(src->funcs == &funcs_8888)
+        {
+            for(y = src_rect->top; y < src_rect->bottom; y++)
+            {
+                dst_pixel = dst_start;
+                src_pixel = src_start;
+                for(x = src_rect->left; x < src_rect->right; x++)
+                {
+                    src_val = *src_pixel++;
+                    *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >> 16) & 0x0000ff) |
+                                                                     ( src_val        & 0x00ff00) |
+                                                                     ((src_val << 16) & 0xff0000) );
+                }
+                dst_start += dst->stride;
+                src_start += src->stride / 4;
+            }
+        }
+        else
+        {
+            FIXME("Unsupported conversion: 32 -> 8\n");
+            return FALSE;
+        }
+        break;
+    }
+
+    case 16:
+    {
+        WORD *src_start = get_pixel_ptr_16(src, src_rect->left, src_rect->top), *src_pixel;
+        if(src->funcs == &funcs_555)
+        {
+            for(y = src_rect->top; y < src_rect->bottom; y++)
+            {
+                dst_pixel = dst_start;
+                src_pixel = src_start;
+                for(x = src_rect->left; x < src_rect->right; x++)
+                {
+                    src_val = *src_pixel++;
+                    *dst_pixel++ = colorref_to_pixel_colortable(dst, ((src_val >>  7) & 0x0000f8) | ((src_val >> 12) & 0x000007) |
+                                                                     ((src_val <<  6) & 0x00f800) | ((src_val <<  1) & 0x000700) |
+                                                                     ((src_val << 19) & 0xf80000) | ((src_val << 14) & 0x070000) );
+                }
+                dst_start += dst->stride;
+                src_start += src->stride / 2;
+            }
+        }
+        else
+        {
+            FIXME("Unsupported conversion: 16 -> 8\n");
+            return FALSE;
+        }
+        break;
+    }
+
+    default:
+        FIXME("Unsupported conversion: %d -> 8\n", src->bit_count);
+        return FALSE;
+
+    }
+    return TRUE;
+}
+
 static BOOL convert_to_null(dib_info *dst, const dib_info *src, const RECT *src_rect)
 {
     return TRUE;
@@ -561,6 +735,14 @@ const primitive_funcs funcs_16 =
     convert_to_16
 };
 
+const primitive_funcs funcs_8 =
+{
+    solid_rects_8,
+    pattern_rects_8,
+    colorref_to_pixel_colortable,
+    convert_to_8
+};
+
 const primitive_funcs funcs_null =
 {
     solid_rects_null,




More information about the wine-cvs mailing list