gdi32: Add a helper function to compute the list of rectangles to paint after clipping.
This commit is contained in:
parent
5b93bb9800
commit
b761d0e1c6
|
@ -576,28 +576,17 @@ static DWORD blend_rect( dib_info *dst, const RECT *dst_rect, const dib_info *sr
|
||||||
HRGN clip, BLENDFUNCTION blend )
|
HRGN clip, BLENDFUNCTION blend )
|
||||||
{
|
{
|
||||||
POINT origin;
|
POINT origin;
|
||||||
RECT clipped_rect;
|
struct clipped_rects clipped_rects;
|
||||||
const WINEREGION *clip_data;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
origin.x = src_rect->left;
|
if (!get_clipped_rects( dst, dst_rect, clip, &clipped_rects )) return ERROR_SUCCESS;
|
||||||
origin.y = src_rect->top;
|
for (i = 0; i < clipped_rects.count; i++)
|
||||||
|
|
||||||
if (clip == NULL) dst->funcs->blend_rect( dst, dst_rect, src, &origin, blend );
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
clip_data = get_wine_region( clip );
|
origin.x = src_rect->left + clipped_rects.rects[i].left - dst_rect->left;
|
||||||
for (i = 0; i < clip_data->numRects; i++)
|
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 );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
free_clipped_rects( &clipped_rects );
|
||||||
return ERROR_SUCCESS;
|
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 )
|
static BOOL gradient_rect( dib_info *dib, TRIVERTEX *v, int mode, HRGN clip )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
RECT rect, clipped_rect;
|
struct clipped_rects clipped_rects;
|
||||||
|
RECT rect;
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
if (mode == GRADIENT_FILL_TRIANGLE)
|
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.right = v[1].x;
|
||||||
rect.bottom = v[1].y;
|
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 );
|
if (!(ret = dib->funcs->gradient_rect( dib, &clipped_rects.rects[i], v, mode ))) break;
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
else if (!is_rect_empty( &rect )) ret = dib->funcs->gradient_rect( dib, &rect, v, mode );
|
free_clipped_rects( &clipped_rects );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,48 @@ DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
|
||||||
return ERROR_SUCCESS;
|
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, ®ion->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
|
* add_extra_clipping_region
|
||||||
*
|
*
|
||||||
* Temporarily add a region to the current clipping region.
|
* Temporarily add a region to the current clipping region.
|
||||||
|
|
|
@ -212,6 +212,13 @@ typedef struct
|
||||||
DWORD octant;
|
DWORD octant;
|
||||||
} bres_params;
|
} 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 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 update_brush_rop( dibdrv_physdev *pdev, INT rop ) DECLSPEC_HIDDEN;
|
||||||
extern void reset_dash_origin(dibdrv_physdev *pdev) 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 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 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 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 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 void restore_clipping_region( dibdrv_physdev *pdev, HRGN rgn ) DECLSPEC_HIDDEN;
|
||||||
extern int clip_line(const POINT *start, const POINT *end, const RECT *clip,
|
extern int clip_line(const POINT *start, const POINT *end, const RECT *clip,
|
||||||
const bres_params *params, POINT *pt1, POINT *pt2) DECLSPEC_HIDDEN;
|
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 */
|
/* 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 )
|
static inline int edge_coord( int y, int x1, int y1, int x2, int y2 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 )
|
COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
|
||||||
{
|
{
|
||||||
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
|
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
|
||||||
int i;
|
struct clipped_rects clipped_rects;
|
||||||
|
RECT rect;
|
||||||
POINT pt;
|
POINT pt;
|
||||||
DWORD pixel;
|
DWORD pixel;
|
||||||
const WINEREGION *clip = get_wine_region( pdev->clip );
|
|
||||||
|
|
||||||
TRACE( "(%p, %d, %d, %08x)\n", dev, x, y, color );
|
TRACE( "(%p, %d, %d, %08x)\n", dev, x, y, color );
|
||||||
|
|
||||||
pt.x = x;
|
pt.x = x;
|
||||||
pt.y = y;
|
pt.y = y;
|
||||||
LPtoDP( dev->hdc, &pt, 1 );
|
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 */
|
/* SetPixel doesn't do the 1bpp massaging like other fg colors */
|
||||||
pixel = get_pixel_color( pdev, color, FALSE );
|
pixel = get_pixel_color( pdev, color, FALSE );
|
||||||
color = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
|
color = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
|
||||||
|
|
||||||
for (i = 0; i < clip->numRects; i++)
|
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 );
|
||||||
if (pt_in_rect( clip->rects + i, pt ))
|
free_clipped_rects( &clipped_rects );
|
||||||
{
|
|
||||||
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 );
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,12 +430,6 @@ static inline void offset_rect( RECT *rect, int offset_x, int offset_y )
|
||||||
rect->bottom += 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 )
|
static inline void get_bounding_rect( RECT *rect, int x, int y, int width, int height )
|
||||||
{
|
{
|
||||||
rect->left = x;
|
rect->left = x;
|
||||||
|
|
Loading…
Reference in New Issue