Huw Davies : gdi32: Add support for DIB pattern brush fills.

Alexandre Julliard julliard at winehq.org
Thu May 12 13:57:51 CDT 2011


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu May 12 12:46:50 2011 +0100

gdi32: Add support for DIB pattern brush fills.

---

 dlls/gdi32/dibdrv/dibdrv.h     |    1 +
 dlls/gdi32/dibdrv/objects.c    |  101 +++++++++++++++++++++++++++++++++++----
 dlls/gdi32/dibdrv/primitives.c |   79 +++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+), 11 deletions(-)

diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index 1982866..a502c72 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -38,6 +38,7 @@ static inline DC *get_dibdrv_dc( PHYSDEV dev )
 typedef struct primitive_funcs
 {
     void        (* solid_rects)(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor);
+    void      (* pattern_rects)(const dib_info *dib, int num, const RECT *rc, const POINT *orign, const dib_info *brush, void *and_bits, void *xor_bits);
     DWORD (* colorref_to_pixel)(const dib_info *dib, COLORREF color);
 } primitive_funcs;
 
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index dde7a96..795bd5e 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <assert.h>
 #include <stdlib.h>
 
 #include "gdi_private.h"
@@ -956,17 +957,6 @@ static BOOL solid_brush(dibdrv_physdev *pdev, int num, RECT *rects)
     return TRUE;
 }
 
-/**********************************************************************
- *             pattern_brush
- *
- * Fill a number of rectangles with the pattern brush
- * FIXME: Should we insist l < r && t < b?  Currently we assume this.
- */
-static BOOL pattern_brush(dibdrv_physdev *pdev, int num, RECT *rects)
-{
-    return FALSE;
-}
-
 static void free_pattern_brush_bits( dibdrv_physdev *pdev )
 {
     HeapFree(GetProcessHeap(), 0, pdev->brush_and_bits);
@@ -981,6 +971,95 @@ void free_pattern_brush( dibdrv_physdev *pdev )
     free_dib_info( &pdev->brush_dib, TRUE );
 }
 
+static BOOL create_pattern_brush_bits(dibdrv_physdev *pdev)
+{
+    DWORD size = pdev->brush_dib.height * abs(pdev->brush_dib.stride);
+    DWORD *brush_bits = pdev->brush_dib.bits;
+    DWORD *and_bits, *xor_bits;
+
+    assert(pdev->brush_and_bits == NULL);
+    assert(pdev->brush_xor_bits == NULL);
+
+    and_bits = pdev->brush_and_bits = HeapAlloc(GetProcessHeap(), 0, size);
+    xor_bits = pdev->brush_xor_bits = HeapAlloc(GetProcessHeap(), 0, size);
+
+    if(!and_bits || !xor_bits)
+    {
+        ERR("Failed to create pattern brush bits\n");
+        free_pattern_brush_bits( pdev );
+        return FALSE;
+    }
+
+    if(pdev->brush_dib.stride < 0)
+        brush_bits = (DWORD*)((BYTE*)brush_bits + (pdev->brush_dib.height - 1) * pdev->brush_dib.stride);
+
+    while(size)
+    {
+        calc_and_xor_masks(pdev->brush_rop, *brush_bits++, and_bits++, xor_bits++);
+        size -= 4;
+    }
+
+    if(pdev->brush_dib.stride < 0)
+    {
+        /* Update the bits ptrs if the dib is bottom up.  The subtraction is because stride is -ve */
+        pdev->brush_and_bits = (BYTE*)pdev->brush_and_bits - (pdev->brush_dib.height - 1) * pdev->brush_dib.stride;
+        pdev->brush_xor_bits = (BYTE*)pdev->brush_xor_bits - (pdev->brush_dib.height - 1) * pdev->brush_dib.stride;
+    }
+
+    return TRUE;
+}
+
+/**********************************************************************
+ *             pattern_brush
+ *
+ * Fill a number of rectangles with the pattern brush
+ * FIXME: Should we insist l < r && t < b?  Currently we assume this.
+ */
+static BOOL pattern_brush(dibdrv_physdev *pdev, int num, RECT *rects)
+{
+    int i, j;
+    const WINEREGION *clip;
+    POINT origin;
+
+    if(pdev->brush_and_bits == NULL)
+        if(!create_pattern_brush_bits(pdev))
+            return FALSE;
+
+    GetBrushOrgEx(pdev->dev.hdc, &origin);
+
+    clip = get_wine_region(pdev->clip);
+    for(i = 0; i < num; i++)
+    {
+        for(j = 0; j < clip->numRects; j++)
+        {
+            RECT rect = rects[i];
+
+            /* Optimize unclipped case */
+            if(clip->rects[j].top <= rect.top && clip->rects[j].bottom >= rect.bottom &&
+               clip->rects[j].left <= rect.left && clip->rects[j].right >= rect.right)
+            {
+                pdev->dib.funcs->pattern_rects(&pdev->dib, 1, &rect, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits);
+                break;
+            }
+
+            if(clip->rects[j].top >= rect.bottom) break;
+            if(clip->rects[j].bottom <= rect.top) continue;
+
+            if(clip->rects[j].right > rect.left && clip->rects[j].left < rect.right)
+            {
+                rect.left   = max(rect.left,   clip->rects[j].left);
+                rect.top    = max(rect.top,    clip->rects[j].top);
+                rect.right  = min(rect.right,  clip->rects[j].right);
+                rect.bottom = min(rect.bottom, clip->rects[j].bottom);
+
+                pdev->dib.funcs->pattern_rects(&pdev->dib, 1, &rect, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits);
+            }
+        }
+    }
+    release_wine_region(pdev->clip);
+    return TRUE;
+}
+
 void update_brush_rop( dibdrv_physdev *pdev, INT rop )
 {
     pdev->brush_rop = rop;
diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c
index a35877e..6dec478 100644
--- a/dlls/gdi32/dibdrv/primitives.c
+++ b/dlls/gdi32/dibdrv/primitives.c
@@ -50,6 +50,82 @@ static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD
     return;
 }
 
+static inline INT calc_offset(INT edge, INT size, INT origin)
+{
+    INT offset;
+
+    if(edge - origin >= 0)
+        offset = (edge - origin) % size;
+    else
+    {
+        offset = (origin - edge) % size;
+        if(offset) offset = size - offset;
+    }
+    return offset;
+}
+
+static inline POINT calc_brush_offset(const RECT *rc, const dib_info *brush, const POINT *origin)
+{
+    POINT offset;
+
+    offset.x = calc_offset(rc->left, brush->width,  origin->x);
+    offset.y = calc_offset(rc->top,  brush->height, origin->y);
+
+    return offset;
+}
+
+static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const POINT *origin,
+                             const dib_info *brush, void *and_bits, void *xor_bits)
+{
+    DWORD *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_32(dib, rc->left, rc->top);
+        start_and = (DWORD*)and_bits + offset.y * brush->stride / 4;
+        start_xor = (DWORD*)xor_bits + offset.y * brush->stride / 4;
+
+        for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4)
+        {
+            and_ptr = start_and + offset.x;
+            xor_ptr = start_xor + offset.x;
+
+            for(x = rc->left, ptr = start; x < rc->right; x++)
+            {
+                do_rop_32(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 / 4;
+                start_xor += brush->stride / 4;
+            }
+        }
+    }
+}
+
+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)
+{
+    return;
+}
+
 static DWORD colorref_to_pixel_888(const dib_info *dib, COLORREF color)
 {
     return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
@@ -88,17 +164,20 @@ static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color)
 const primitive_funcs funcs_8888 =
 {
     solid_rects_32,
+    pattern_rects_32,
     colorref_to_pixel_888
 };
 
 const primitive_funcs funcs_32 =
 {
     solid_rects_32,
+    pattern_rects_32,
     colorref_to_pixel_masks
 };
 
 const primitive_funcs funcs_null =
 {
     solid_rects_null,
+    pattern_rects_null,
     colorref_to_pixel_null
 };




More information about the wine-cvs mailing list