2 * DIB driver graphics operations.
4 * Copyright 2011 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "gdi_private.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dib);
28 static RECT get_device_rect( HDC hdc, int left, int top, int right, int bottom, BOOL rtl_correction )
36 if (rtl_correction && GetLayout( hdc ) & LAYOUT_RTL)
38 /* shift the rectangle so that the right border is included after mirroring */
39 /* it would be more correct to do this after LPtoDP but that's not what Windows does */
43 LPtoDP( hdc, (POINT *)&rect, 2 );
44 if (rect.left > rect.right)
47 rect.left = rect.right;
50 if (rect.top > rect.bottom)
53 rect.top = rect.bottom;
59 /***********************************************************************
62 BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
64 PHYSDEV next = GET_NEXT_PHYSDEV( dev, pLineTo );
65 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
68 GetCurrentPositionEx(dev->hdc, pts);
72 LPtoDP(dev->hdc, pts, 2);
74 reset_dash_origin(pdev);
76 if(defer_pen(pdev) || !pdev->pen_line(pdev, pts, pts + 1))
77 return next->funcs->pLineTo( next, x, y );
82 /***********************************************************************
85 * Returns the binary rop that is equivalent to the provided ternary rop
86 * if the src bits are ignored.
88 static inline INT get_rop2_from_rop(INT rop)
90 return (((rop >> 18) & 0x0c) | ((rop >> 16) & 0x03)) + 1;
93 /***********************************************************************
96 BOOL CDECL dibdrv_PatBlt( PHYSDEV dev, INT x, INT y, INT width, INT height, DWORD rop )
98 PHYSDEV next = GET_NEXT_PHYSDEV( dev, pPatBlt );
99 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
100 INT rop2 = get_rop2_from_rop(rop);
101 RECT rect = get_device_rect( dev->hdc, x, y, x + width, y + height, TRUE );
104 TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev, x, y, width, height, rop);
106 if(defer_brush(pdev))
107 return next->funcs->pPatBlt( next, x, y, width, height, rop );
109 update_brush_rop( pdev, rop2 );
111 done = pdev->brush_rects( pdev, 1, &rect );
113 update_brush_rop( pdev, GetROP2(dev->hdc) );
116 return next->funcs->pPatBlt( next, x, y, width, height, rop );
121 /***********************************************************************
124 BOOL CDECL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
126 PHYSDEV next = GET_NEXT_PHYSDEV( dev, pPaintRgn );
127 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
128 const WINEREGION *region;
132 TRACE("%p, %p\n", dev, rgn);
134 if(defer_brush(pdev)) return next->funcs->pPaintRgn( next, rgn );
136 region = get_wine_region( rgn );
137 if(!region) return FALSE;
139 for(i = 0; i < region->numRects; i++)
141 rect = get_device_rect( dev->hdc, region->rects[i].left, region->rects[i].top,
142 region->rects[i].right, region->rects[i].bottom, FALSE );
143 pdev->brush_rects( pdev, 1, &rect );
146 release_wine_region( rgn );
150 /***********************************************************************
153 BOOL CDECL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
155 PHYSDEV next = GET_NEXT_PHYSDEV( dev, pRectangle );
156 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
157 RECT rect = get_device_rect( dev->hdc, left, top, right, bottom, TRUE );
160 TRACE("(%p, %d, %d, %d, %d)\n", dev, left, top, right, bottom);
162 if(rect.left == rect.right || rect.top == rect.bottom) return TRUE;
164 if(defer_pen(pdev) || defer_brush(pdev))
165 return next->funcs->pRectangle( next, left, top, right, bottom );
167 reset_dash_origin(pdev);
169 /* 4 pts going anti-clockwise starting from top-right */
170 pts[0].x = pts[3].x = rect.right - 1;
171 pts[0].y = pts[1].y = rect.top;
172 pts[1].x = pts[2].x = rect.left;
173 pts[2].y = pts[3].y = rect.bottom - 1;
175 pdev->pen_line(pdev, pts , pts + 1);
176 pdev->pen_line(pdev, pts + 1, pts + 2);
177 pdev->pen_line(pdev, pts + 2, pts + 3);
178 pdev->pen_line(pdev, pts + 3, pts );
180 /* FIXME: Will need updating when we support wide pens */
187 pdev->brush_rects(pdev, 1, &rect);