mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
gdi32: Use the get_clipped_rects helper in the blitting functions.
This commit is contained in:
parent
d0f110e2a9
commit
56373bc491
@ -467,14 +467,24 @@ static int get_overlap( const dib_info *dst, const RECT *dst_rect,
|
||||
}
|
||||
|
||||
static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src, const RECT *src_rect,
|
||||
HRGN clip, INT rop2 )
|
||||
const struct clipped_rects *clipped_rects, INT rop2 )
|
||||
{
|
||||
POINT origin;
|
||||
RECT clipped_rect;
|
||||
const WINEREGION *clip_data;
|
||||
int i, start, end, overlap;
|
||||
const RECT *rects;
|
||||
int i, count, start, end, overlap;
|
||||
DWORD and = 0, xor = 0;
|
||||
|
||||
if (clipped_rects)
|
||||
{
|
||||
rects = clipped_rects->rects;
|
||||
count = clipped_rects->count;
|
||||
}
|
||||
else
|
||||
{
|
||||
rects = dst_rect;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
switch (rop2)
|
||||
{
|
||||
case R2_NOT: and = ~0u;
|
||||
@ -482,92 +492,63 @@ static DWORD copy_rect( dib_info *dst, const RECT *dst_rect, const dib_info *src
|
||||
case R2_WHITE: xor = ~0u;
|
||||
/* fall through */
|
||||
case R2_BLACK:
|
||||
if (clip)
|
||||
{
|
||||
clip_data = get_wine_region( clip );
|
||||
for (i = 0; i < clip_data->numRects; i++)
|
||||
if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
|
||||
dst->funcs->solid_rects( dst, 1, &clipped_rect, and, xor );
|
||||
release_wine_region( clip );
|
||||
}
|
||||
else dst->funcs->solid_rects( dst, 1, dst_rect, and, xor );
|
||||
dst->funcs->solid_rects( dst, count, rects, and, xor );
|
||||
/* fall through */
|
||||
case R2_NOP:
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
origin.x = src_rect->left;
|
||||
origin.y = src_rect->top;
|
||||
overlap = get_overlap( dst, dst_rect, src, src_rect );
|
||||
|
||||
if (clip == NULL) dst->funcs->copy_rect( dst, dst_rect, src, &origin, rop2, overlap );
|
||||
else
|
||||
if (overlap & OVERLAP_BELOW)
|
||||
{
|
||||
clip_data = get_wine_region( clip );
|
||||
if (overlap & OVERLAP_BELOW)
|
||||
if (overlap & OVERLAP_RIGHT) /* right to left, bottom to top */
|
||||
{
|
||||
if (overlap & OVERLAP_RIGHT) /* right to left, bottom to top */
|
||||
for (i = count - 1; i >= 0; i--)
|
||||
{
|
||||
for (i = clip_data->numRects - 1; i >= 0; i--)
|
||||
{
|
||||
if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
|
||||
{
|
||||
origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
|
||||
origin.y = src_rect->top + clipped_rect.top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &clipped_rect, src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
origin.x = src_rect->left + rects[i].left - dst_rect->left;
|
||||
origin.y = src_rect->top + rects[i].top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &rects[i], src, &origin, rop2, overlap );
|
||||
}
|
||||
else /* left to right, bottom to top */
|
||||
}
|
||||
else /* left to right, bottom to top */
|
||||
{
|
||||
for (start = count - 1; start >= 0; start = end)
|
||||
{
|
||||
for (start = clip_data->numRects - 1; start >= 0; start = end)
|
||||
{
|
||||
for (end = start - 1; end >= 0; end--)
|
||||
if (clip_data->rects[start].top != clip_data->rects[end].top) break;
|
||||
for (end = start - 1; end >= 0; end--)
|
||||
if (rects[start].top != rects[end].top) break;
|
||||
|
||||
for (i = end + 1; i <= start; i++)
|
||||
{
|
||||
if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
|
||||
{
|
||||
origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
|
||||
origin.y = src_rect->top + clipped_rect.top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &clipped_rect, src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
for (i = end + 1; i <= start; i++)
|
||||
{
|
||||
origin.x = src_rect->left + rects[i].left - dst_rect->left;
|
||||
origin.y = src_rect->top + rects[i].top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &rects[i], src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (overlap & OVERLAP_RIGHT) /* right to left, top to bottom */
|
||||
}
|
||||
else if (overlap & OVERLAP_RIGHT) /* right to left, top to bottom */
|
||||
{
|
||||
for (start = 0; start < count; start = end)
|
||||
{
|
||||
for (start = 0; start < clip_data->numRects; start = end)
|
||||
{
|
||||
for (end = start + 1; end < clip_data->numRects; end++)
|
||||
if (clip_data->rects[start].top != clip_data->rects[end].top) break;
|
||||
for (end = start + 1; end < count; end++)
|
||||
if (rects[start].top != rects[end].top) break;
|
||||
|
||||
for (i = end - 1; i >= start; i--)
|
||||
{
|
||||
if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
|
||||
{
|
||||
origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
|
||||
origin.y = src_rect->top + clipped_rect.top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &clipped_rect, src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* left to right, top to bottom */
|
||||
{
|
||||
for (i = 0; i < clip_data->numRects; i++)
|
||||
for (i = end - 1; i >= start; i--)
|
||||
{
|
||||
if (intersect_rect( &clipped_rect, dst_rect, clip_data->rects + i ))
|
||||
{
|
||||
origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
|
||||
origin.y = src_rect->top + clipped_rect.top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &clipped_rect, src, &origin, rop2, overlap );
|
||||
}
|
||||
origin.x = src_rect->left + rects[i].left - dst_rect->left;
|
||||
origin.y = src_rect->top + rects[i].top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &rects[i], src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
release_wine_region( clip );
|
||||
}
|
||||
else /* left to right, top to bottom */
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
origin.x = src_rect->left + rects[i].left - dst_rect->left;
|
||||
origin.y = src_rect->top + rects[i].top - dst_rect->top;
|
||||
dst->funcs->copy_rect( dst, &rects[i], src, &origin, rop2, overlap );
|
||||
}
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -734,7 +715,7 @@ static DWORD create_tmp_dib( const dib_info *copy, int width, int height, dib_in
|
||||
}
|
||||
|
||||
static DWORD execute_rop( dibdrv_physdev *pdev, const RECT *dst_rect, dib_info *src,
|
||||
const RECT *src_rect, HRGN clip, DWORD rop )
|
||||
const RECT *src_rect, const struct clipped_rects *clipped_rects, DWORD rop )
|
||||
{
|
||||
dib_info *dibs[3], *result = src, tmp;
|
||||
RECT rects[3];
|
||||
@ -777,13 +758,16 @@ static DWORD execute_rop( dibdrv_physdev *pdev, const RECT *dst_rect, dib_info *
|
||||
case OP_ARGS(TMP,DST):
|
||||
copy_rect( dibs[OP_DST(*opcode)], &rects[OP_DST(*opcode)],
|
||||
dibs[OP_SRC(*opcode)], &rects[OP_SRC(*opcode)],
|
||||
OP_DST(*opcode) == DST ? clip : NULL, OP_ROP(*opcode) );
|
||||
OP_DST(*opcode) == DST ? clipped_rects : NULL, OP_ROP(*opcode) );
|
||||
break;
|
||||
case OP_ARGS(PAT,DST):
|
||||
update_brush_rop( pdev, OP_ROP(*opcode) );
|
||||
pdev->brush_rects( pdev, dibs[DST], clipped_rects->count, clipped_rects->rects );
|
||||
update_brush_rop( pdev, GetROP2(pdev->dev.hdc) );
|
||||
break;
|
||||
case OP_ARGS(PAT,SRC):
|
||||
update_brush_rop( pdev, OP_ROP(*opcode) );
|
||||
pdev->brush_rects( pdev, dibs[OP_DST(*opcode)], 1, &rects[OP_DST(*opcode)],
|
||||
OP_DST(*opcode) == DST ? clip : NULL );
|
||||
pdev->brush_rects( pdev, dibs[SRC], 1, &rects[SRC] );
|
||||
update_brush_rop( pdev, GetROP2(pdev->dev.hdc) );
|
||||
break;
|
||||
}
|
||||
@ -791,7 +775,8 @@ static DWORD execute_rop( dibdrv_physdev *pdev, const RECT *dst_rect, dib_info *
|
||||
|
||||
if (dibs[TMP]) free_dib_info( dibs[TMP] );
|
||||
|
||||
if (result == src) copy_rect( dibs[DST], &rects[DST], dibs[SRC], &rects[SRC], clip, R2_COPYPEN );
|
||||
if (result == src)
|
||||
copy_rect( dibs[DST], &rects[DST], dibs[SRC], &rects[SRC], clipped_rects, R2_COPYPEN );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -941,6 +926,7 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
|
||||
struct bitblt_coords *dst, DWORD rop )
|
||||
{
|
||||
dib_info *dib = NULL, stand_alone;
|
||||
struct clipped_rects clipped_rects;
|
||||
DWORD ret;
|
||||
dib_info src_dib;
|
||||
HRGN saved_clip = NULL;
|
||||
@ -990,17 +976,21 @@ DWORD dibdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
|
||||
clip = pdev->clip;
|
||||
}
|
||||
|
||||
if (!get_clipped_rects( dib, &dst->visrect, clip, &clipped_rects ))
|
||||
{
|
||||
ret = ERROR_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!rop_uses_pat( rop ))
|
||||
{
|
||||
int rop2 = ((rop >> 16) & 0xf) + 1;
|
||||
ret = copy_rect( dib, &dst->visrect, &src_dib, &src->visrect, clip, rop2 );
|
||||
ret = copy_rect( dib, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = execute_rop( pdev, &dst->visrect, &src_dib, &src->visrect, clip, rop );
|
||||
ret = execute_rop( pdev, &dst->visrect, &src_dib, &src->visrect, &clipped_rects, rop );
|
||||
}
|
||||
|
||||
if (saved_clip) restore_clipping_region( pdev, saved_clip );
|
||||
goto done;
|
||||
|
||||
update_format:
|
||||
@ -1010,6 +1000,7 @@ update_format:
|
||||
ret = ERROR_BAD_FORMAT;
|
||||
|
||||
done:
|
||||
if (saved_clip) restore_clipping_region( pdev, saved_clip );
|
||||
if (hbitmap) GDI_ReleaseObj( hbitmap );
|
||||
return ret;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ typedef struct dibdrv_physdev
|
||||
void *brush_pattern_bits;
|
||||
UINT brush_pattern_usage;
|
||||
HBITMAP brush_pattern_bitmap;
|
||||
BOOL (* brush_rects)(struct dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects, HRGN clip);
|
||||
BOOL (* brush_rects)(struct dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects);
|
||||
} dibdrv_physdev;
|
||||
|
||||
#define DEFER_PEN 2
|
||||
@ -230,8 +230,7 @@ extern void copy_dib_color_info(dib_info *dst, const dib_info *src) DECLSPEC_HID
|
||||
extern BOOL convert_dib(dib_info *dst, const dib_info *src) DECLSPEC_HIDDEN;
|
||||
extern COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL *got_pixel, DWORD *pixel ) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_pixel_color(dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup) DECLSPEC_HIDDEN;
|
||||
extern BOOL brush_rects( dibdrv_physdev *pdev, int num, const RECT *rects ) DECLSPEC_HIDDEN;
|
||||
extern void solid_rects( dib_info *dib, int num, const RECT *rects, const rop_mask *color, HRGN region ) DECLSPEC_HIDDEN;
|
||||
extern BOOL brush_rect( dibdrv_physdev *pdev, const RECT *rect ) DECLSPEC_HIDDEN;
|
||||
extern int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) DECLSPEC_HIDDEN;
|
||||
extern HRGN add_extra_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) DECLSPEC_HIDDEN;
|
||||
extern void restore_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) DECLSPEC_HIDDEN;
|
||||
|
@ -482,7 +482,7 @@ BOOL dibdrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
|
||||
TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev, dst->x, dst->y, dst->width, dst->height, rop);
|
||||
|
||||
update_brush_rop( pdev, rop2 );
|
||||
ret = brush_rects( pdev, 1, &dst->visrect );
|
||||
ret = brush_rect( pdev, &dst->visrect );
|
||||
update_brush_rop( pdev, GetROP2(dev->hdc) );
|
||||
return ret;
|
||||
}
|
||||
@ -506,7 +506,7 @@ BOOL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
|
||||
{
|
||||
rect = get_device_rect( dev->hdc, region->rects[i].left, region->rects[i].top,
|
||||
region->rects[i].right, region->rects[i].bottom, FALSE );
|
||||
brush_rects( pdev, 1, &rect );
|
||||
brush_rect( pdev, &rect );
|
||||
}
|
||||
|
||||
release_wine_region( rgn );
|
||||
@ -602,7 +602,7 @@ BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
|
||||
rect.right -= 1;
|
||||
rect.bottom -= 1;
|
||||
|
||||
brush_rects(pdev, 1, &rect);
|
||||
brush_rect(pdev, &rect);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1364,44 +1364,18 @@ COLORREF dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
|
||||
return next->funcs->pSetDCPenColor( next, color );
|
||||
}
|
||||
|
||||
void solid_rects( dib_info *dib, int num, const RECT *rects, const rop_mask *color, HRGN region )
|
||||
{
|
||||
int i, j;
|
||||
const WINEREGION *clip;
|
||||
|
||||
if (!region)
|
||||
{
|
||||
dib->funcs->solid_rects( dib, num, rects, color->and, color->xor );
|
||||
return;
|
||||
}
|
||||
|
||||
clip = get_wine_region( region );
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
for(j = 0; j < clip->numRects; j++)
|
||||
{
|
||||
RECT clipped_rect;
|
||||
|
||||
if (intersect_rect( &clipped_rect, rects + i, clip->rects + j ))
|
||||
dib->funcs->solid_rects( dib, 1, &clipped_rect, color->and, color->xor );
|
||||
}
|
||||
}
|
||||
release_wine_region( region );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* solid_brush
|
||||
*
|
||||
* Fill a number of rectangles with the solid brush
|
||||
*/
|
||||
static BOOL solid_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects, HRGN region)
|
||||
static BOOL solid_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects)
|
||||
{
|
||||
rop_mask brush_color;
|
||||
DWORD color = get_pixel_color( pdev, pdev->brush_colorref, TRUE );
|
||||
|
||||
calc_rop_masks( pdev->brush_rop, color, &brush_color );
|
||||
solid_rects( dib, num, rects, &brush_color, region );
|
||||
dib->funcs->solid_rects( dib, num, rects, brush_color.and, brush_color.xor );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1617,10 +1591,8 @@ static BOOL select_pattern_brush( dibdrv_physdev *pdev, BOOL *needs_reselect )
|
||||
* 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, dib_info *dib, int num, const RECT *rects, HRGN region)
|
||||
static BOOL pattern_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects)
|
||||
{
|
||||
int i, j;
|
||||
const WINEREGION *clip;
|
||||
POINT origin;
|
||||
BOOL needs_reselect = FALSE;
|
||||
|
||||
@ -1648,50 +1620,13 @@ static BOOL pattern_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RE
|
||||
|
||||
GetBrushOrgEx(pdev->dev.hdc, &origin);
|
||||
|
||||
clip = get_wine_region( region );
|
||||
dib->funcs->pattern_rects( dib, num, rects, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits );
|
||||
|
||||
if (!clip)
|
||||
{
|
||||
dib->funcs->pattern_rects( dib, num, rects, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits );
|
||||
goto done;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
dib->funcs->pattern_rects( 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);
|
||||
|
||||
dib->funcs->pattern_rects( dib, 1, &rect, &origin, &pdev->brush_dib, pdev->brush_and_bits, pdev->brush_xor_bits );
|
||||
}
|
||||
}
|
||||
}
|
||||
release_wine_region( region );
|
||||
|
||||
done:
|
||||
if (needs_reselect) free_pattern_brush( pdev );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL null_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects, HRGN region)
|
||||
static BOOL null_brush(dibdrv_physdev *pdev, dib_info *dib, int num, const RECT *rects)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@ -1777,7 +1712,13 @@ COLORREF dibdrv_SetDCBrushColor( PHYSDEV dev, COLORREF color )
|
||||
return next->funcs->pSetDCBrushColor( next, color );
|
||||
}
|
||||
|
||||
BOOL brush_rects(dibdrv_physdev *pdev, int num, const RECT *rects)
|
||||
BOOL brush_rect(dibdrv_physdev *pdev, const RECT *rect)
|
||||
{
|
||||
return pdev->brush_rects( pdev, &pdev->dib, num, rects, pdev->clip );
|
||||
struct clipped_rects clipped_rects;
|
||||
BOOL ret;
|
||||
|
||||
if (!get_clipped_rects( &pdev->dib, rect, pdev->clip, &clipped_rects )) return TRUE;
|
||||
ret = pdev->brush_rects( pdev, &pdev->dib, clipped_rects.count, clipped_rects.rects );
|
||||
free_clipped_rects( &clipped_rects );
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user