gdi32: Add support for DIB pattern brush fills.
This commit is contained in:
parent
3c70a26e4b
commit
5b28336c26
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue