From c20285218b55a08c1ad3a9a5e049d50913319de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?= Date: Fri, 8 Feb 2019 10:05:10 -0500 Subject: [PATCH] gdi32/dibdrv: Clip segment points to dib rect in wide_line_segment(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sergio Gómez Del Real Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/dibdrv/objects.c | 43 ++++++++++++++++++++++++++++--------- dlls/gdi32/gdi_private.h | 8 +++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index f95475a662a..26710dd1aa0 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -1334,15 +1334,21 @@ static void add_join( dibdrv_physdev *pdev, HRGN region, HRGN round_cap, const P { HRGN join; POINT pts[4]; + RECT rect; switch (pdev->pen_join) { default: FIXME( "Unknown line join %x\n", pdev->pen_join ); /* fall through */ case PS_JOIN_ROUND: - OffsetRgn( round_cap, pt->x, pt->y ); - CombineRgn( region, region, round_cap, RGN_OR ); - OffsetRgn( round_cap, -pt->x, -pt->y ); + GetRgnBox( round_cap, &rect ); + offset_rect( &rect, pt->x, pt->y ); + if (clip_rect_to_dib( &pdev->dib, &rect )) + { + OffsetRgn( round_cap, pt->x, pt->y ); + CombineRgn( region, region, round_cap, RGN_OR ); + OffsetRgn( round_cap, -pt->x, -pt->y ); + } return; case PS_JOIN_MITER: @@ -1358,7 +1364,9 @@ static void add_join( dibdrv_physdev *pdev, HRGN region, HRGN round_cap, const P break; } - CombineRgn( region, region, join, RGN_OR ); + GetRgnBox( join, &rect ); + if (clip_rect_to_dib( &pdev->dib, &rect )) + CombineRgn( region, region, join, RGN_OR ); DeleteObject( join ); return; } @@ -1367,7 +1375,7 @@ static BOOL wide_line_segment( dibdrv_physdev *pdev, HRGN total, const POINT *pt_1, const POINT *pt_2, int dx, int dy, BOOL need_cap_1, BOOL need_cap_2, struct face *face_1, struct face *face_2 ) { - RECT rect; + RECT rect, clip_rect; BOOL sq_cap_1 = need_cap_1 && (pdev->pen_endcap == PS_ENDCAP_SQUARE); BOOL sq_cap_2 = need_cap_2 && (pdev->pen_endcap == PS_ENDCAP_SQUARE); @@ -1381,7 +1389,9 @@ static BOOL wide_line_segment( dibdrv_physdev *pdev, HRGN total, rect.bottom = rect.top + pdev->pen_width; if ((sq_cap_1 && dx > 0) || (sq_cap_2 && dx < 0)) rect.left -= pdev->pen_width / 2; if ((sq_cap_2 && dx > 0) || (sq_cap_1 && dx < 0)) rect.right += pdev->pen_width / 2; - add_rect_to_region( total, &rect ); + clip_rect = rect; + if (clip_rect_to_dib( &pdev->dib, &clip_rect )) + add_rect_to_region( total, &clip_rect ); if (dx > 0) { face_1->start.x = face_1->end.x = rect.left; @@ -1405,7 +1415,9 @@ static BOOL wide_line_segment( dibdrv_physdev *pdev, HRGN total, rect.right = rect.left + pdev->pen_width; if ((sq_cap_1 && dy > 0) || (sq_cap_2 && dy < 0)) rect.top -= pdev->pen_width / 2; if ((sq_cap_2 && dy > 0) || (sq_cap_1 && dy < 0)) rect.bottom += pdev->pen_width / 2; - add_rect_to_region( total, &rect ); + clip_rect = rect; + if (clip_rect_to_dib( &pdev->dib, &clip_rect )) + add_rect_to_region( total, &clip_rect ); if (dy > 0) { face_1->start.x = face_2->end.x = rect.left; @@ -1475,9 +1487,20 @@ static BOOL wide_line_segment( dibdrv_physdev *pdev, HRGN total, seg_pts[3].y += wide_half.x; } - segment = CreatePolygonRgn( seg_pts, 4, ALTERNATE ); - CombineRgn( total, total, segment, RGN_OR ); - DeleteObject( segment ); + if (dx > 0 && dy > 0) + set_rect( &clip_rect, seg_pts[0].x, seg_pts[1].y, seg_pts[2].x, seg_pts[3].y ); + else if (dx > 0 && dy < 0) + set_rect( &clip_rect, seg_pts[1].x, seg_pts[2].y, seg_pts[3].x, seg_pts[0].y ); + else if (dx < 0 && dy > 0) + set_rect( &clip_rect, seg_pts[3].x, seg_pts[0].y, seg_pts[1].x, seg_pts[2].y ); + else + set_rect( &clip_rect, seg_pts[2].x, seg_pts[3].y, seg_pts[0].x, seg_pts[1].y ); + if (clip_rect_to_dib( &pdev->dib, &clip_rect )) + { + segment = CreatePolygonRgn( seg_pts, 4, ALTERNATE ); + CombineRgn( total, total, segment, RGN_OR ); + DeleteObject( segment ); + } face_1->start = seg_pts[0]; face_1->end = seg_pts[1]; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 920cd1e7bfd..01473dd7e26 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -521,6 +521,14 @@ static inline void offset_rect( RECT *rect, int offset_x, int offset_y ) rect->bottom += offset_y; } +static inline void set_rect( RECT *rect, int left, int top, int right, int bottom ) +{ + rect->left = left; + rect->top = top; + rect->right = right; + rect->bottom = bottom; +} + static inline void order_rect( RECT *rect ) { if (rect->left > rect->right)