Alexandre Julliard : gdi32: Implement 16-bpp gradient dithering.

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


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

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

gdi32: Implement 16-bpp gradient dithering.

---

 dlls/gdi32/dibdrv/primitives.c |   81 ++++++++++++++++++++++++---------------
 1 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c
index e882b8a..00213de 100644
--- a/dlls/gdi32/dibdrv/primitives.c
+++ b/dlls/gdi32/dibdrv/primitives.c
@@ -3996,6 +3996,25 @@ static inline DWORD gradient_rgb_24( const TRIVERTEX *v, unsigned int pos, unsig
     return r << 16 | g << 8 | b;
 }
 
+static inline WORD gradient_rgb_555( const TRIVERTEX *v, unsigned int pos, unsigned int len,
+                                     unsigned int x, unsigned int y )
+{
+    static const BYTE matrix[4][4] =
+    {
+        {  0,  8,  2, 10 },
+        { 12,  4, 14,  6 },
+        {  3, 11,  1,  9 },
+        { 15,  7, 13,  5 }
+    };
+    int r = (v[0].Red   * (len - pos) + v[1].Red   * pos) / len / 128 + matrix[y % 4][x % 4];
+    int g = (v[0].Green * (len - pos) + v[1].Green * pos) / len / 128 + matrix[y % 4][x % 4];
+    int b = (v[0].Blue  * (len - pos) + v[1].Blue  * pos) / len / 128 + matrix[y % 4][x % 4];
+    r = min( 31, max( 0, r / 16 ));
+    g = min( 31, max( 0, g / 16 ));
+    b = min( 31, max( 0, b / 16 ));
+    return (r << 10) | (g << 5) | b;
+}
+
 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 );
@@ -4113,29 +4132,25 @@ static void gradient_rect_24( const dib_info *dib, const RECT *rc, const TRIVERT
 
 static void gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
 {
-    WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
+    WORD *ptr = get_pixel_ptr_16( 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] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
-        }
-
-        for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 2)
-            memcpy( ptr + dib->stride / 2, ptr, (rc->right - rc->left) * 2 );
+        for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
+            for (x = rc->left; x < rc->right; x++)
+                ptr[x] = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
+        for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
+            memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
         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 / 2)
         {
-            DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
-            val = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f);
-            for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
-            ptr += dib->stride / 2;
+            WORD values[4];
+            for (x = 0; x < 4; x++) values[x] = gradient_rgb_555( 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 % 4];
         }
         break;
     }
@@ -4143,33 +4158,37 @@ static void gradient_rect_555( const dib_info *dib, const RECT *rc, const TRIVER
 
 static void gradient_rect_16( const dib_info *dib, const RECT *rc, const TRIVERTEX *v, int mode )
 {
-    WORD *ptr = get_pixel_ptr_16( dib, rc->left, rc->top );
+    WORD *ptr = get_pixel_ptr_16( 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] = (put_field((val >> 16), dib->red_shift,   dib->red_len)   |
-                      put_field((val >>  8), dib->green_shift, dib->green_len) |
-                      put_field( val,        dib->blue_shift,  dib->blue_len));
-        }
+        for (y = rc->top; y < min( rc->top + 4, rc->bottom ); y++, ptr += dib->stride / 2)
+            for (x = rc->left; x < rc->right; x++)
+            {
+                WORD val = gradient_rgb_555( v, x - v[0].x, v[1].x - v[0].x, x, y );
+                ptr[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
+                          put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
+                          put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
 
-        for (y = rc->top + 1; y < rc->bottom; y++, ptr += dib->stride / 2)
-            memcpy( ptr + dib->stride / 2, ptr, (rc->right - rc->left) * 2 );
+            }
+        for (ptr += rc->left; y < rc->bottom; y++, ptr += dib->stride / 2)
+            memcpy( ptr, ptr - dib->stride * 2, (rc->right - rc->left) * 2 );
         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 / 2)
         {
-            DWORD val = gradient_rgb_24( v, y - v[0].y, v[1].y - v[0].y );
-            val = (put_field((val >> 16), dib->red_shift,   dib->red_len)   |
-                   put_field((val >>  8), dib->green_shift, dib->green_len) |
-                   put_field( val,        dib->blue_shift,  dib->blue_len));
-            for (x = 0; x < rc->right - rc->left; x++) ptr[x] = val;
-            ptr += dib->stride / 2;
+            WORD values[4];
+            for (x = 0; x < 4; x++)
+            {
+                WORD val = gradient_rgb_555( v, y - v[0].y, v[1].y - v[0].y, x, y );
+                values[x] = (put_field(((val >> 7) & 0xf8) | ((val >> 12) & 0x07), dib->red_shift,   dib->red_len)   |
+                             put_field(((val >> 2) & 0xf8) | ((val >> 7)  & 0x07), dib->green_shift, dib->green_len) |
+                             put_field(((val << 3) & 0xf8) | ((val >> 2)  & 0x07), dib->blue_shift,  dib->blue_len));
+            }
+            for (x = rc->left; x < rc->right; x++) ptr[x] = values[x % 4];
         }
         break;
     }




More information about the wine-cvs mailing list