wininet: Don't change the verb if the server response is HTTP_STATUS_REDIRECT_KEEP_VERB.
[wine] / dlls / gdi32 / dibdrv / graphics.c
1 /*
2  * DIB driver graphics operations.
3  *
4  * Copyright 2011 Huw Davies
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "gdi_private.h"
22 #include "dibdrv.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(dib);
27
28 static RECT get_device_rect( HDC hdc, int left, int top, int right, int bottom, BOOL rtl_correction )
29 {
30     RECT rect;
31
32     rect.left   = left;
33     rect.top    = top;
34     rect.right  = right;
35     rect.bottom = bottom;
36     if (rtl_correction && GetLayout( hdc ) & LAYOUT_RTL)
37     {
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 */
40         rect.left--;
41         rect.right--;
42     }
43     LPtoDP( hdc, (POINT *)&rect, 2 );
44     if (rect.left > rect.right)
45     {
46         int tmp = rect.left;
47         rect.left = rect.right;
48         rect.right = tmp;
49     }
50     if (rect.top > rect.bottom)
51     {
52         int tmp = rect.top;
53         rect.top = rect.bottom;
54         rect.bottom = tmp;
55     }
56     return rect;
57 }
58
59 /***********************************************************************
60  *           dibdrv_LineTo
61  */
62 BOOL CDECL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
63 {
64     PHYSDEV next = GET_NEXT_PHYSDEV( dev, pLineTo );
65     dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
66     POINT pts[2];
67
68     GetCurrentPositionEx(dev->hdc, pts);
69     pts[1].x = x;
70     pts[1].y = y;
71
72     LPtoDP(dev->hdc, pts, 2);
73
74     reset_dash_origin(pdev);
75
76     if(defer_pen(pdev) || !pdev->pen_line(pdev, pts, pts + 1))
77         return next->funcs->pLineTo( next, x, y );
78
79     return TRUE;
80 }
81
82 /***********************************************************************
83  *           get_rop2_from_rop
84  *
85  * Returns the binary rop that is equivalent to the provided ternary rop
86  * if the src bits are ignored.
87  */
88 static inline INT get_rop2_from_rop(INT rop)
89 {
90     return (((rop >> 18) & 0x0c) | ((rop >> 16) & 0x03)) + 1;
91 }
92
93 /***********************************************************************
94  *           dibdrv_PatBlt
95  */
96 BOOL CDECL dibdrv_PatBlt( PHYSDEV dev, INT x, INT y, INT width, INT height, DWORD rop )
97 {
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 );
102     BOOL done;
103
104     TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev, x, y, width, height, rop);
105
106     if(defer_brush(pdev))
107         return next->funcs->pPatBlt( next, x, y, width, height, rop );
108
109     update_brush_rop( pdev, rop2 );
110
111     done = pdev->brush_rects( pdev, 1, &rect );
112
113     update_brush_rop( pdev, GetROP2(dev->hdc) );
114
115     if(!done)
116         return next->funcs->pPatBlt( next, x, y, width, height, rop );
117
118     return TRUE;
119 }
120
121 /***********************************************************************
122  *           dibdrv_PaintRgn
123  */
124 BOOL CDECL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
125 {
126     PHYSDEV next = GET_NEXT_PHYSDEV( dev, pPaintRgn );
127     dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
128     const WINEREGION *region;
129     int i;
130     RECT rect;
131
132     TRACE("%p, %p\n", dev, rgn);
133
134     if(defer_brush(pdev)) return next->funcs->pPaintRgn( next, rgn );
135
136     region = get_wine_region( rgn );
137     if(!region) return FALSE;
138
139     for(i = 0; i < region->numRects; i++)
140     {
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 );
144     }
145
146     release_wine_region( rgn );
147     return TRUE;
148 }
149
150 /***********************************************************************
151  *           dibdrv_Rectangle
152  */
153 BOOL CDECL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
154 {
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 );
158     POINT pts[4];
159
160     TRACE("(%p, %d, %d, %d, %d)\n", dev, left, top, right, bottom);
161
162     if(rect.left == rect.right || rect.top == rect.bottom) return TRUE;
163
164     if(defer_pen(pdev) || defer_brush(pdev))
165         return next->funcs->pRectangle( next, left, top, right, bottom );
166
167     reset_dash_origin(pdev);
168
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;
174
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    );
179
180     /* FIXME: Will need updating when we support wide pens */
181
182     rect.left   += 1;
183     rect.top    += 1;
184     rect.right  -= 1;
185     rect.bottom -= 1;
186
187     pdev->brush_rects(pdev, 1, &rect);
188
189     return TRUE;
190 }