Alexandre Julliard : gdi32: Implement 8-bpp and 4-bpp gradient dithering.

Alexandre Julliard julliard at winehq.org
Tue Nov 29 14:20:39 CST 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Nov 29 14:22:59 2011 +0100

gdi32: Implement 8-bpp and 4-bpp gradient dithering.

---

 dlls/gdi32/dibdrv/primitives.c |   99 ++++++++++++++++++++++++---------------
 1 files changed, 61 insertions(+), 38 deletions(-)

diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c
index 00213de..5938a1b 100644
--- a/dlls/gdi32/dibdrv/primitives.c
+++ b/dlls/gdi32/dibdrv/primitives.c
@@ -4015,6 +4015,34 @@ static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsig
     return (r << 10) | (g << 5) | b;
 }
 
+static inline BYTE gradient_rgb_8( const dib_info *dib, const TRIVERTEX *v,
+                                   unsigned int pos, unsigned int len, unsigned int x, unsigned int y )
+{
+    static const BYTE matrix[16][16] =
+    {
+        {   0, 128,  32, 160,   8, 136,  40, 168,   2, 130,  34, 162,  10, 138,  42, 170 },
+        { 192,  64, 224,  96, 200,  72, 232, 104, 194,  66, 226,  98, 202,  74, 234, 106 },
+        {  48, 176,  16, 144,  56, 184,  24, 152,  50, 178,  18, 146,  58, 186,  26, 154 },
+        { 240, 112, 208,  80, 248, 120, 216,  88, 242, 114, 210,  82, 250, 122, 218,  90 },
+        {  12, 140,  44, 172,   4, 132,  36, 164,  14, 142,  46, 174,   6, 134,  38, 166 },
+        { 204,  76, 236, 108, 196,  68, 228, 100, 206,  78, 238, 110, 198,  70, 230, 102 },
+        {  60, 188,  28, 156,  52, 180,  20, 148,  62, 190,  30, 158,  54, 182,  22, 150 },
+        { 252, 124, 220,  92, 244, 116, 212,  84, 254, 126, 222,  94, 246, 118, 214,  86 },
+        {   3, 131,  35, 163,  11, 139,  43, 171,   1, 129,  33, 161,   9, 137,  41, 169 },
+        { 195,  67, 227,  99, 203,  75, 235, 107, 193,  65, 225,  97, 201,  73, 233, 105 },
+        {  51, 179,  19, 147,  59, 187,  27, 155,  49, 177,  17, 145,  57, 185,  25, 153 },
+        { 243, 115, 211,  83, 251, 123, 219,  91, 241, 113, 209,  81, 249, 121, 217,  89 },
+        {  15, 143,  47, 175,   7, 135,  39, 167,  13, 141,  45, 173,   5, 133,  37, 165 },
+        { 207,  79, 239, 111, 199,  71, 231, 103, 205,  77, 237, 109, 197,  69, 229, 101 },
+        {  63, 191,  31, 159,  55, 183,  23, 151,  61, 189,  29, 157,  53, 181,  21, 149 },
+        { 255, 127, 223,  95, 247, 119, 215,  87, 253, 125, 221,  93, 245, 117, 213,  85 },
+    };
+    BYTE r = ((v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + matrix[y % 16][x % 16]) / 256;
+    BYTE g = ((v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + matrix[y % 16][x % 16]) / 256;
+    BYTE b = ((v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + matrix[y % 16][x % 16]) / 256;
+    return rgb_to_pixel_colortable( dib, r * 127, g * 127, b * 127 );
+}
+
 static void gradient_rect_8888( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
 {
     DWORD *ptr = get_pixel_ptr_32( dib, rc->left, rc->top );
@@ -4196,29 +4224,26 @@ static void gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERT
 
 static void gradient_rect_8( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
 {
-    BYTE *ptr = get_pixel_ptr_8( dib, rc->left, rc->top );
+    BYTE *ptr = get_pixel_ptr_8( dib, 0, rc->top );
     int x, y;
 
     switch (mode)
     {
     case GRADIENT_FILL_RECT_H:
-        for (x = 0; x < rc->right - rc->left; x++)
-        {
-            DWORD val = gradient_rgb_24( v, x + rc->left - v[0].x, v[1].x - v[0].x );
-            ptr[x] = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
-        }
-
-        for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
-            memcpy( ptr + dib->stride, ptr, rc->right - rc->left );
+        for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
+            for (x = rc->left; x < rc->right; x++)
+                ptr[x] = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
+        for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride)
+            memcpy( ptr, ptr - dib->stride * 16, rc->right - rc->left );
         break;
 
     case GRADIENT_FILL_RECT_V:
-        for (y = rc->top; y < rc->bottom; y++)
+        for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
         {
-            DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
-            val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
-            for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
-            ptr += dib->stride;
+            BYTE values[16];
+            for (x = 0; x < 16; x++)
+                values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
+            for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 16];
         }
         break;
     }
@@ -4232,44 +4257,42 @@ static void gradient_rect_4( const dib_info *dib, const RECT *rc, const TRIVERTE
     switch (mode)
     {
     case GRADIENT_FILL_RECT_H:
-        for (x = rc->left; x < rc->right; x++)
+        for (y = rc->top; y < min( rc->top + 16, rc->bottom ); y++, ptr += dib->stride)
         {
-            DWORD val = gradient_rgb_24( v, x - v[0].x, v[1].x - v[0].x );
-            val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
-            if (x & 1)
-                ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
-            else
-                ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
+            for (x = rc->left; x < rc->right; x++)
+            {
+                BYTE val = gradient_rgb_8( dib, v, x - v[0].x, v[1].x - v[0].x, x, y );
+                if (x & 1)
+                    ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
+                else
+                    ptr[x / 2] = (val << 4) | (ptr[x / 2] & 0x0f);
+            }
         }
-
-        for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride)
+        for ( ; y < rc->bottom; y++, ptr += dib->stride)
         {
             x = rc->left;
             if (x & 1)
             {
-                ptr[dib->stride + x / 2] = (ptr[x / 2] & 0x0f) | (ptr[dib->stride + x / 2] & 0xf0);
+                ptr[x / 2] = (ptr[x / 2 - 16 * dib->stride] & 0x0f) | (ptr[x / 2] & 0xf0);
                 x++;
             }
-            for (; x < rc->right - 1; x += 2) ptr[dib->stride + x / 2] = ptr[x / 2];
+            for (; x < rc->right - 1; x += 2) ptr[x / 2] = ptr[x / 2 - 16 * dib->stride];
             if (x < rc->right)
-                ptr[dib->stride + x / 2] = (ptr[dib->stride + x / 2] & 0x0f) | (ptr[x / 2] & 0xf0);
+                ptr[x / 2] = (ptr[x / 2] & 0x0f) | (ptr[x / 2 - 16 * dib->stride] & 0xf0);
         }
         break;
 
     case GRADIENT_FILL_RECT_V:
-        for (y = rc->top; y < rc->bottom; y++)
+        for (y = rc->top; y < rc->bottom; y++, ptr += dib->stride)
         {
-            DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
-            val = rgb_lookup_colortable( dib, val >> 16, val >> 8, val );
-            x = rc->left;
-            if (x & 1)
-            {
-                ptr[x / 2] = val | (ptr[x / 2] & 0xf0);
-                x++;
-            }
-            for (; x < rc->right - 1; x += 2) ptr[x / 2] = (val << 4) | val;
-            if (x < rc->right) ptr[x / 2] = (ptr[x / 2] & 0x0f) | (val << 4);
-            ptr += dib->stride;
+            BYTE values[16];
+            for (x = 0; x < 16; x++)
+                values[x] = gradient_rgb_8( dib, v, y - v[0].y, v[1].y - v[0].y, x, y );
+            for (x = rc->left; x < rc->right; x++)
+                if (x & 1)
+                    ptr[x / 2] = values[x % 16] | (ptr[x / 2] & 0xf0);
+                else
+                    ptr[x / 2] = (values[x % 16] << 4) | (ptr[x / 2] & 0x0f);
         }
         break;
     }




More information about the wine-cvs mailing list