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