From 64ed56366c6ac64c8d5a1e818b0480ff533ef5b2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 28 Dec 2011 13:52:58 +0100 Subject: [PATCH] gdi32: Use a region to render geometric and wide pens in PolyPolyline. --- dlls/gdi32/dibdrv/dibdrv.h | 2 +- dlls/gdi32/dibdrv/graphics.c | 45 +++++++++++++++++++++--------------- dlls/gdi32/dibdrv/objects.c | 2 ++ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index fa8d445e8a..ba8c0a4da3 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -84,7 +84,7 @@ typedef struct dibdrv_physdev /* pen */ COLORREF pen_colorref; DWORD pen_style, pen_endcap, pen_join; - BOOL pen_is_ext; + BOOL pen_uses_region, pen_is_ext; int pen_width; dash_pattern pen_pattern; dash_pos dash_pos; diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index e8b45a1e95..d43b30bda1 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -517,14 +517,27 @@ BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO PHYSDEV next = GET_NEXT_PHYSDEV( dev, pPolyPolyline ); DWORD max_points = 0, i; POINT *points; + BOOL ret = TRUE; + INT rop = GetROP2( dev->hdc ); + HRGN outline = 0; if (defer_pen( pdev )) return next->funcs->pPolyPolyline( next, pt, counts, polylines ); - for (i = 0; i < polylines; i++) max_points = max( counts[i], max_points ); + for (i = 0; i < polylines; i++) + { + if (counts[i] < 2) return FALSE; + max_points = max( counts[i], max_points ); + } points = HeapAlloc( GetProcessHeap(), 0, max_points * sizeof(*pt) ); if (!points) return FALSE; + if (pdev->pen_uses_region && !(outline = CreateRectRgn( 0, 0, 0, 0 ))) + { + HeapFree( GetProcessHeap(), 0, points ); + return FALSE; + } + for (i = 0; i < polylines; i++) { memcpy( points, pt, counts[i] * sizeof(*pt) ); @@ -532,11 +545,18 @@ BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO LPtoDP( dev->hdc, points, counts[i] ); reset_dash_origin( pdev ); - pdev->pen_lines( pdev, counts[i], points, FALSE, 0 ); + pdev->pen_lines( pdev, counts[i], points, FALSE, outline ); + } + + if (outline) + { + if (pdev->clip) CombineRgn( outline, outline, pdev->clip, RGN_AND ); + ret = pen_rect( pdev, NULL, outline, rop ); + DeleteObject( outline ); } HeapFree( GetProcessHeap(), 0, points ); - return TRUE; + return ret; } /*********************************************************************** @@ -544,23 +564,10 @@ BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO */ BOOL dibdrv_Polyline( PHYSDEV dev, const POINT* pt, INT count ) { - dibdrv_physdev *pdev = get_dibdrv_pdev(dev); - PHYSDEV next = GET_NEXT_PHYSDEV( dev, pPolyline ); - POINT *points; + DWORD counts[1] = { count }; - if (defer_pen( pdev )) return next->funcs->pPolyline( next, pt, count ); - - points = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*pt) ); - if (!points) return FALSE; - - memcpy( points, pt, count * sizeof(*pt) ); - LPtoDP( dev->hdc, points, count ); - - reset_dash_origin( pdev ); - pdev->pen_lines( pdev, count, points, FALSE, 0 ); - - HeapFree( GetProcessHeap(), 0, points ); - return TRUE; + if (count < 0) return FALSE; + return dibdrv_PolyPolyline( dev, pt, counts, 1 ); } /*********************************************************************** diff --git a/dlls/gdi32/dibdrv/objects.c b/dlls/gdi32/dibdrv/objects.c index dd7ddb70d4..197b220d0b 100644 --- a/dlls/gdi32/dibdrv/objects.c +++ b/dlls/gdi32/dibdrv/objects.c @@ -1615,6 +1615,7 @@ HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) break; case PS_NULL: + pdev->pen_width = 0; pdev->pen_lines = null_pen_lines; pdev->defer &= ~DEFER_PEN; break; @@ -1637,6 +1638,7 @@ HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen ) break; } + pdev->pen_uses_region = (logpen.lopnStyle & PS_GEOMETRIC || pdev->pen_width > 1); pdev->pen_is_ext = (elp != NULL); HeapFree( GetProcessHeap(), 0, elp );