gdi32: Add a helper function to compute the list of rectangles to paint after clipping.

This commit is contained in:
Alexandre Julliard 2011-12-27 14:31:11 +01:00
parent 5b93bb9800
commit b761d0e1c6
5 changed files with 83 additions and 61 deletions

View File

@ -576,28 +576,17 @@ static DWORD blend_rect( dib_info *dst, const RECT *dst_rect, const dib_info *sr
HRGN clip, BLENDFUNCTION blend )
{
POINT origin;
RECT clipped_rect;
const WINEREGION *clip_data;
struct clipped_rects clipped_rects;
int i;
origin.x = src_rect->left;
origin.y = src_rect->top;
if (clip == NULL) dst->funcs->blend_rect( dst, dst_rect, src, &origin, blend );
else
if (!get_clipped_rects( dst, dst_rect, clip, &clipped_rects )) return ERROR_SUCCESS;
for (i = 0; i < clipped_rects.count; i++)
{
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 ))
{
origin.x = src_rect->left + clipped_rect.left - dst_rect->left;
origin.y = src_rect->top + clipped_rect.top - dst_rect->top;
dst->funcs->blend_rect( dst, &clipped_rect, src, &origin, blend );
}
}
release_wine_region( clip );
origin.x = src_rect->left + clipped_rects.rects[i].left - dst_rect->left;
origin.y = src_rect->top + clipped_rects.rects[i].top - dst_rect->top;
dst->funcs->blend_rect( dst, &clipped_rects.rects[i], src, &origin, blend );
}
free_clipped_rects( &clipped_rects );
return ERROR_SUCCESS;
}
@ -679,7 +668,8 @@ static void get_gradient_triangle_vertices( const GRADIENT_TRIANGLE *tri, const
static BOOL gradient_rect( dib_info *dib, TRIVERTEX *v, int mode, HRGN clip )
{
int i;
RECT rect, clipped_rect;
struct clipped_rects clipped_rects;
RECT rect;
BOOL ret = TRUE;
if (mode == GRADIENT_FILL_TRIANGLE)
@ -696,26 +686,13 @@ static BOOL gradient_rect( dib_info *dib, TRIVERTEX *v, int mode, HRGN clip )
rect.right = v[1].x;
rect.bottom = v[1].y;
}
rect.left = max( rect.left, 0 );
rect.top = max( rect.top, 0 );
rect.right = min( rect.right, dib->width );
rect.bottom = min( rect.bottom, dib->height );
if (clip)
if (!get_clipped_rects( dib, &rect, clip, &clipped_rects )) return TRUE;
for (i = 0; i < clipped_rects.count; i++)
{
const WINEREGION *clip_data = get_wine_region( clip );
for (i = 0; i < clip_data->numRects; i++)
{
if (intersect_rect( &clipped_rect, &rect, clip_data->rects + i ))
{
if (!(ret = dib->funcs->gradient_rect( dib, &clipped_rect, v, mode ))) break;
}
}
release_wine_region( clip );
if (!(ret = dib->funcs->gradient_rect( dib, &clipped_rects.rects[i], v, mode ))) break;
}
else if (!is_rect_empty( &rect )) ret = dib->funcs->gradient_rect( dib, &rect, v, mode );
free_clipped_rects( &clipped_rects );
return ret;
}

View File

@ -257,7 +257,48 @@ DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
return ERROR_SUCCESS;
}
/***********************************************************************
int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects )
{
const WINEREGION *region;
RECT rect, *out = clip_rects->buffer;
int i;
init_clipped_rects( clip_rects );
rect.left = 0;
rect.top = 0;
rect.right = dib->width;
rect.bottom = dib->height;
if (rc && !intersect_rect( &rect, &rect, rc )) return 0;
if (!clip)
{
*out = rect;
clip_rects->count = 1;
return 1;
}
if (!(region = get_wine_region( clip ))) return 0;
for (i = 0; i < region->numRects; i++)
{
if (region->rects[i].top >= rect.bottom) break;
if (!intersect_rect( out, &rect, &region->rects[i] )) continue;
out++;
if (out == &clip_rects->buffer[sizeof(clip_rects->buffer) / sizeof(RECT)])
{
clip_rects->rects = HeapAlloc( GetProcessHeap(), 0, region->numRects * sizeof(RECT) );
if (!clip_rects->rects) return 0;
memcpy( clip_rects->rects, clip_rects->buffer, (out - clip_rects->buffer) * sizeof(RECT) );
out = clip_rects->rects + (out - clip_rects->buffer);
}
}
release_wine_region( clip );
clip_rects->count = out - clip_rects->rects;
return clip_rects->count;
}
/***********************************************************************
* add_extra_clipping_region
*
* Temporarily add a region to the current clipping region.

View File

@ -212,6 +212,13 @@ typedef struct
DWORD octant;
} bres_params;
struct clipped_rects
{
RECT *rects;
int count;
RECT buffer[32];
};
extern void get_rop_codes(INT rop, struct rop_codes *codes) DECLSPEC_HIDDEN;
extern void update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN;
extern void reset_dash_origin(dibdrv_physdev *pdev) DECLSPEC_HIDDEN;
@ -225,11 +232,23 @@ extern COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL
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 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;
extern int clip_line(const POINT *start, const POINT *end, const RECT *clip,
const bres_params *params, POINT *pt1, POINT *pt2) DECLSPEC_HIDDEN;
static inline void init_clipped_rects( struct clipped_rects *clip_rects )
{
clip_rects->count = 0;
clip_rects->rects = clip_rects->buffer;
}
static inline void free_clipped_rects( struct clipped_rects *clip_rects )
{
if (clip_rects->rects != clip_rects->buffer) HeapFree( GetProcessHeap(), 0, clip_rects->rects );
}
/* compute the x coordinate corresponding to y on the specified edge */
static inline int edge_coord( int y, int x1, int y1, int x2, int y2 )
{

View File

@ -606,36 +606,27 @@ BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
{
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
int i;
struct clipped_rects clipped_rects;
RECT rect;
POINT pt;
DWORD pixel;
const WINEREGION *clip = get_wine_region( pdev->clip );
TRACE( "(%p, %d, %d, %08x)\n", dev, x, y, color );
pt.x = x;
pt.y = y;
LPtoDP( dev->hdc, &pt, 1 );
rect.left = pt.x;
rect.top = pt.y;
rect.right = rect.left + 1;
rect.bottom = rect.top + 1;
/* SetPixel doesn't do the 1bpp massaging like other fg colors */
pixel = get_pixel_color( pdev, color, FALSE );
color = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
for (i = 0; i < clip->numRects; i++)
{
if (pt_in_rect( clip->rects + i, pt ))
{
RECT rect;
rect.left = pt.x;
rect.top = pt.y;
rect.right = rect.left + 1;
rect.bottom = rect.top + 1;
pdev->dib.funcs->solid_rects( &pdev->dib, 1, &rect, 0, pixel );
break;
}
}
release_wine_region( pdev->clip );
if (!get_clipped_rects( &pdev->dib, &rect, pdev->clip, &clipped_rects )) return color;
pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects, 0, pixel );
free_clipped_rects( &clipped_rects );
return color;
}

View File

@ -430,12 +430,6 @@ static inline void offset_rect( RECT *rect, int offset_x, int offset_y )
rect->bottom += offset_y;
}
static inline BOOL pt_in_rect( const RECT *rect, POINT pt )
{
return ((pt.x >= rect->left) && (pt.x < rect->right) &&
(pt.y >= rect->top) && (pt.y < rect->bottom));
}
static inline void get_bounding_rect( RECT *rect, int x, int y, int width, int height )
{
rect->left = x;