Alexandre Julliard : gdi32: Clip solid pen regions to the DIB rectangle to avoid overflows.
Alexandre Julliard
julliard at winehq.org
Mon Jul 30 14:18:51 CDT 2012
Module: wine
Branch: master
Commit: 6714f16c74180c450edb8b9f9bdba43c14c0b8e0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6714f16c74180c450edb8b9f9bdba43c14c0b8e0
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Jul 30 13:59:04 2012 +0200
gdi32: Clip solid pen regions to the DIB rectangle to avoid overflows.
---
dlls/gdi32/dibdrv/dc.c | 12 +++
dlls/gdi32/dibdrv/dibdrv.h | 1 +
dlls/gdi32/dibdrv/objects.c | 177 +++++++++++++++++++++++++------------------
3 files changed, 116 insertions(+), 74 deletions(-)
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index de64d18..73895c9 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -255,6 +255,18 @@ DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit
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 )
{
const WINEREGION *region;
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index 7802d17..0a99fba 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -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 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 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 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,
diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c
index 0292537..f9736f6 100644
--- a/dlls/gdi32/dibdrv/objects.c
+++ b/dlls/gdi32/dibdrv/objects.c
@@ -654,6 +654,87 @@ static BOOL solid_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end, DWORD
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 )
{
RECT rect;
@@ -667,99 +748,47 @@ static BOOL solid_pen_line_region( dibdrv_physdev *pdev, POINT *start, POINT *en
{
rect.right = end->x;
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)
{
rect.bottom = end->y;
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
{
- INT dx = end->x - start->x, dy = end->y - start->y;
- INT abs_dx = abs(dx), abs_dy = abs(dy);
- DWORD octant = get_octant_mask(dx, dy);
- INT bias = get_bias( octant );
+ bres_params clip_params;
+ struct line_params line_params;
+ POINT p1 = crop_coords( *start ), p2 = crop_coords( *end );
- 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;
- int err_add_1 = 2 * abs_dy - 2 * abs_dx;
- int err_add_2 = 2 * abs_dy;
- int err = 2 * abs_dy - abs_dx;
+ POINT clipped_start, clipped_end;
- if (is_x_increasing( octant ))
- {
- for (rect.right = start->x + 1; rect.right <= end->x; rect.right++)
- {
- if (err + bias > 0)
- {
- add_rect_to_region( region, &rect );
- rect.left = rect.right;
- rect.top += y_inc;
- rect.bottom += y_inc;
- err += err_add_1;
- }
- else err += err_add_2;
- }
- }
- else
+ if (clip_line( &p1, &p2, &rect, &clip_params, &clipped_start, &clipped_end ))
{
- for (rect.left = start->x; rect.left > end->x; rect.left--)
- {
- if (err + bias > 0)
- {
- add_rect_to_region( region, &rect );
- rect.right = rect.left;
- rect.top += y_inc;
- rect.bottom += y_inc;
- err += err_add_1;
- }
- else err += err_add_2;
- }
- }
- }
- 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;
+ int m = abs(clipped_start.x - p1.x);
+ int n = abs(clipped_start.y - p1.y);
- if (is_y_increasing( octant ))
- {
- for (rect.bottom = start->y + 1; rect.bottom <= end->y; rect.bottom++)
+ if (line_params.x_major)
{
- 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;
+ line_params.err_start = 2 * clip_params.dy - clip_params.dx
+ + m * 2 * clip_params.dy - n * 2 * clip_params.dx;
+ line_params.length = abs( clipped_end.x - clipped_start.x ) + 1;
}
- }
- else
- {
- for (rect.top = start->y; rect.top > end->y; rect.top--)
+ else
{
- 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;
+ line_params.err_start = 2 * clip_params.dx - clip_params.dy
+ + n * 2 * clip_params.dx - m * 2 * clip_params.dy;
+ line_params.length = abs( clipped_end.y - clipped_start.y ) + 1;
}
+
+ if (clipped_end.x == p2.x && clipped_end.y == p2.y) line_params.length--;
+ solid_line_region( &pdev->dib, &clipped_start, &line_params, region );
}
}
- /* add final rect */
- add_rect_to_region( region, &rect );
}
return TRUE;
}
More information about the wine-cvs
mailing list