From 56373bc491c5700e80ec76ea50c4a0d24bfb2148 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 27 Dec 2011 14:38:39 +0100 Subject: [PATCH] gdi32: Use the get_clipped_rects helper in the blitting functions. --- dlls/gdi32/dibdrv/bitblt.c | 149 ++++++++++++++++------------------- dlls/gdi32/dibdrv/dibdrv.h | 5 +- dlls/gdi32/dibdrv/graphics.c | 6 +- dlls/gdi32/dibdrv/objects.c | 85 +++----------------- 4 files changed, 88 insertions(+), 157 deletions(-) diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c index b862ebb6da0..cbfd8b09b7d 100644 --- a/dlls/gdi32/dibdrv/bitblt.c +++ b/dlls/gdi32/dibdrv/bitblt.c @@ -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; } diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index c0cbc5b7bfe..2b42b46fe6b 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -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; diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index 2e95d6654d4..0c31c567cc1 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -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; } diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index 3b3d5a3af9e..7a381e7ad9a 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -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; }