gdi32: Clip solid pen regions to the DIB rectangle to avoid overflows.
This commit is contained in:
parent
a9151e5da3
commit
6714f16c74
|
@ -255,6 +255,18 @@ DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int clip_rect_to_dib( const dib_info *dib, RECT *rc )
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
rect.left = max( 0, -dib->rect.left );
|
||||||
|
rect.top = max( 0, -dib->rect.top );
|
||||||
|
rect.right = min( dib->rect.right, dib->width ) - dib->rect.left;
|
||||||
|
rect.bottom = min( dib->rect.bottom, dib->height ) - dib->rect.top;
|
||||||
|
if (is_rect_empty( &rect )) return 0;
|
||||||
|
return intersect_rect( rc, &rect, rc );
|
||||||
|
}
|
||||||
|
|
||||||
int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects )
|
int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects )
|
||||||
{
|
{
|
||||||
const WINEREGION *region;
|
const WINEREGION *region;
|
||||||
|
|
|
@ -244,6 +244,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 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 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 DWORD get_pixel_color(dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup) DECLSPEC_HIDDEN;
|
||||||
|
extern int clip_rect_to_dib( const dib_info *dib, RECT *rc ) DECLSPEC_HIDDEN;
|
||||||
extern int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) DECLSPEC_HIDDEN;
|
extern int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct clipped_rects *clip_rects ) DECLSPEC_HIDDEN;
|
||||||
extern void add_clipped_bounds( dibdrv_physdev *dev, const RECT *rect, HRGN clip ) DECLSPEC_HIDDEN;
|
extern void add_clipped_bounds( dibdrv_physdev *dev, const RECT *rect, HRGN clip ) 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,
|
||||||
|
|
|
@ -654,6 +654,87 @@ static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end, DWORD
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void solid_line_region( const dib_info *dib, const POINT *start, const struct line_params *params,
|
||||||
|
HRGN region )
|
||||||
|
{
|
||||||
|
int len, err = params->err_start;
|
||||||
|
RECT rect;
|
||||||
|
|
||||||
|
rect.left = start->x;
|
||||||
|
rect.top = start->y;
|
||||||
|
rect.right = start->x + 1;
|
||||||
|
rect.bottom = start->y + 1;
|
||||||
|
|
||||||
|
if (params->x_major)
|
||||||
|
{
|
||||||
|
if (params->x_inc > 0)
|
||||||
|
{
|
||||||
|
for (len = params->length; len; len--, rect.right++)
|
||||||
|
{
|
||||||
|
if (err + params->bias > 0)
|
||||||
|
{
|
||||||
|
add_rect_to_region( region, &rect );
|
||||||
|
rect.left = rect.right;
|
||||||
|
rect.top += params->y_inc;
|
||||||
|
rect.bottom += params->y_inc;
|
||||||
|
err += params->err_add_1;
|
||||||
|
}
|
||||||
|
else err += params->err_add_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (len = params->length; len; len--, rect.left--)
|
||||||
|
{
|
||||||
|
if (err + params->bias > 0)
|
||||||
|
{
|
||||||
|
add_rect_to_region( region, &rect );
|
||||||
|
rect.right = rect.left;
|
||||||
|
rect.top += params->y_inc;
|
||||||
|
rect.bottom += params->y_inc;
|
||||||
|
err += params->err_add_1;
|
||||||
|
}
|
||||||
|
else err += params->err_add_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (params->y_inc > 0)
|
||||||
|
{
|
||||||
|
for (len = params->length; len; len--, rect.bottom++)
|
||||||
|
{
|
||||||
|
if (err + params->bias > 0)
|
||||||
|
{
|
||||||
|
add_rect_to_region( region, &rect );
|
||||||
|
rect.top = rect.bottom;
|
||||||
|
rect.left += params->x_inc;
|
||||||
|
rect.right += params->x_inc;
|
||||||
|
err += params->err_add_1;
|
||||||
|
}
|
||||||
|
else err += params->err_add_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (len = params->length; len; len--, rect.top--)
|
||||||
|
{
|
||||||
|
if (err + params->bias > 0)
|
||||||
|
{
|
||||||
|
add_rect_to_region( region, &rect );
|
||||||
|
rect.bottom = rect.top;
|
||||||
|
rect.left += params->x_inc;
|
||||||
|
rect.right += params->x_inc;
|
||||||
|
err += params->err_add_1;
|
||||||
|
}
|
||||||
|
else err += params->err_add_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* add final rect */
|
||||||
|
add_rect_to_region( region, &rect );
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL solid_pen_line_region( dibdrv_physdev *pdev, POINT *start, POINT *end, HRGN region )
|
static BOOL solid_pen_line_region( dibdrv_physdev *pdev, POINT *start, POINT *end, HRGN region )
|
||||||
{
|
{
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
@ -667,99 +748,47 @@ static BOOL solid_pen_line_region( dibdrv_physdev *pdev, POINT *start, POINT *en
|
||||||
{
|
{
|
||||||
rect.right = end->x;
|
rect.right = end->x;
|
||||||
order_end_points(&rect.left, &rect.right);
|
order_end_points(&rect.left, &rect.right);
|
||||||
add_rect_to_region( region, &rect );
|
if (clip_rect_to_dib( &pdev->dib, &rect )) add_rect_to_region( region, &rect );
|
||||||
}
|
}
|
||||||
else if(start->x == end->x)
|
else if(start->x == end->x)
|
||||||
{
|
{
|
||||||
rect.bottom = end->y;
|
rect.bottom = end->y;
|
||||||
order_end_points(&rect.top, &rect.bottom);
|
order_end_points(&rect.top, &rect.bottom);
|
||||||
add_rect_to_region( region, &rect );
|
if (clip_rect_to_dib( &pdev->dib, &rect )) add_rect_to_region( region, &rect );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
INT dx = end->x - start->x, dy = end->y - start->y;
|
bres_params clip_params;
|
||||||
INT abs_dx = abs(dx), abs_dy = abs(dy);
|
struct line_params line_params;
|
||||||
DWORD octant = get_octant_mask(dx, dy);
|
POINT p1 = crop_coords( *start ), p2 = crop_coords( *end );
|
||||||
INT bias = get_bias( octant );
|
|
||||||
|
|
||||||
if (is_xmajor( octant ))
|
init_bres_params( start, end, &clip_params, &line_params, &rect );
|
||||||
|
if (clip_rect_to_dib( &pdev->dib, &rect ))
|
||||||
{
|
{
|
||||||
int y_inc = is_y_increasing( octant ) ? 1 : -1;
|
POINT clipped_start, clipped_end;
|
||||||
int err_add_1 = 2 * abs_dy - 2 * abs_dx;
|
|
||||||
int err_add_2 = 2 * abs_dy;
|
|
||||||
int err = 2 * abs_dy - abs_dx;
|
|
||||||
|
|
||||||
if (is_x_increasing( octant ))
|
if (clip_line( &p1, &p2, &rect, &clip_params, &clipped_start, &clipped_end ))
|
||||||
{
|
{
|
||||||
for (rect.right = start->x + 1; rect.right <= end->x; rect.right++)
|
int m = abs(clipped_start.x - p1.x);
|
||||||
|
int n = abs(clipped_start.y - p1.y);
|
||||||
|
|
||||||
|
if (line_params.x_major)
|
||||||
{
|
{
|
||||||
if (err + bias > 0)
|
line_params.err_start = 2 * clip_params.dy - clip_params.dx
|
||||||
{
|
+ m * 2 * clip_params.dy - n * 2 * clip_params.dx;
|
||||||
add_rect_to_region( region, &rect );
|
line_params.length = abs( clipped_end.x - clipped_start.x ) + 1;
|
||||||
rect.left = rect.right;
|
|
||||||
rect.top += y_inc;
|
|
||||||
rect.bottom += y_inc;
|
|
||||||
err += err_add_1;
|
|
||||||
}
|
|
||||||
else err += err_add_2;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
for (rect.left = start->x; rect.left > end->x; rect.left--)
|
|
||||||
{
|
{
|
||||||
if (err + bias > 0)
|
line_params.err_start = 2 * clip_params.dx - clip_params.dy
|
||||||
{
|
+ n * 2 * clip_params.dx - m * 2 * clip_params.dy;
|
||||||
add_rect_to_region( region, &rect );
|
line_params.length = abs( clipped_end.y - clipped_start.y ) + 1;
|
||||||
rect.right = rect.left;
|
|
||||||
rect.top += y_inc;
|
|
||||||
rect.bottom += y_inc;
|
|
||||||
err += err_add_1;
|
|
||||||
}
|
|
||||||
else err += err_add_2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clipped_end.x == p2.x && clipped_end.y == p2.y) line_params.length--;
|
||||||
|
solid_line_region( &pdev->dib, &clipped_start, &line_params, region );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int x_inc = is_x_increasing( octant ) ? 1 : -1;
|
|
||||||
int err_add_1 = 2 * abs_dx - 2 * abs_dy;
|
|
||||||
int err_add_2 = 2 * abs_dx;
|
|
||||||
int err = 2 * abs_dx - abs_dy;
|
|
||||||
|
|
||||||
if (is_y_increasing( octant ))
|
|
||||||
{
|
|
||||||
for (rect.bottom = start->y + 1; rect.bottom <= end->y; rect.bottom++)
|
|
||||||
{
|
|
||||||
if (err + bias > 0)
|
|
||||||
{
|
|
||||||
add_rect_to_region( region, &rect );
|
|
||||||
rect.top = rect.bottom;
|
|
||||||
rect.left += x_inc;
|
|
||||||
rect.right += x_inc;
|
|
||||||
err += err_add_1;
|
|
||||||
}
|
|
||||||
else err += err_add_2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (rect.top = start->y; rect.top > end->y; rect.top--)
|
|
||||||
{
|
|
||||||
if (err + bias > 0)
|
|
||||||
{
|
|
||||||
add_rect_to_region( region, &rect );
|
|
||||||
rect.bottom = rect.top;
|
|
||||||
rect.left += x_inc;
|
|
||||||
rect.right += x_inc;
|
|
||||||
err += err_add_1;
|
|
||||||
}
|
|
||||||
else err += err_add_2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* add final rect */
|
|
||||||
add_rect_to_region( region, &rect );
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue