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
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_lines(pdev
, 2, pts
))
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
dibdrv_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, 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
);
103 TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev
, dst
->x
, dst
->y
, dst
->width
, dst
->height
, rop
);
105 if(defer_brush(pdev
))
106 return next
->funcs
->pPatBlt( next
, dst
, rop
);
108 update_brush_rop( pdev
, rop2
);
110 done
= brush_rects( pdev
, 1, &dst
->visrect
);
112 update_brush_rop( pdev
, GetROP2(dev
->hdc
) );
115 return next
->funcs
->pPatBlt( next
, dst
, rop
);
120 /***********************************************************************
123 BOOL
dibdrv_PaintRgn( PHYSDEV dev
, HRGN rgn
)
125 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pPaintRgn
);
126 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
127 const WINEREGION
*region
;
131 TRACE("%p, %p\n", dev
, rgn
);
133 if(defer_brush(pdev
)) return next
->funcs
->pPaintRgn( next
, rgn
);
135 region
= get_wine_region( rgn
);
136 if(!region
) return FALSE
;
138 for(i
= 0; i
< region
->numRects
; i
++)
140 rect
= get_device_rect( dev
->hdc
, region
->rects
[i
].left
, region
->rects
[i
].top
,
141 region
->rects
[i
].right
, region
->rects
[i
].bottom
, FALSE
);
142 brush_rects( pdev
, 1, &rect
);
145 release_wine_region( rgn
);
149 /***********************************************************************
150 * dibdrv_PolyPolyline
152 BOOL
dibdrv_PolyPolyline( PHYSDEV dev
, const POINT
* pt
, const DWORD
* counts
, DWORD polylines
)
154 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
155 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pPolyPolyline
);
156 DWORD max_points
= 0, i
;
159 if (defer_pen( pdev
)) return next
->funcs
->pPolyPolyline( next
, pt
, counts
, polylines
);
161 for (i
= 0; i
< polylines
; i
++) max_points
= max( counts
[i
], max_points
);
163 points
= HeapAlloc( GetProcessHeap(), 0, max_points
* sizeof(*pt
) );
164 if (!points
) return FALSE
;
166 for (i
= 0; i
< polylines
; i
++)
168 memcpy( points
, pt
, counts
[i
] * sizeof(*pt
) );
170 LPtoDP( dev
->hdc
, points
, counts
[i
] );
172 reset_dash_origin( pdev
);
173 pdev
->pen_lines( pdev
, counts
[i
], points
);
176 HeapFree( GetProcessHeap(), 0, points
);
180 /***********************************************************************
183 BOOL
dibdrv_Polyline( PHYSDEV dev
, const POINT
* pt
, INT count
)
185 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
186 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pPolyline
);
189 if (defer_pen( pdev
)) return next
->funcs
->pPolyline( next
, pt
, count
);
191 points
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pt
) );
192 if (!points
) return FALSE
;
194 memcpy( points
, pt
, count
* sizeof(*pt
) );
195 LPtoDP( dev
->hdc
, points
, count
);
197 reset_dash_origin( pdev
);
198 pdev
->pen_lines( pdev
, count
, points
);
200 HeapFree( GetProcessHeap(), 0, points
);
204 /***********************************************************************
207 BOOL
dibdrv_Rectangle( PHYSDEV dev
, INT left
, INT top
, INT right
, INT bottom
)
209 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pRectangle
);
210 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
211 RECT rect
= get_device_rect( dev
->hdc
, left
, top
, right
, bottom
, TRUE
);
214 TRACE("(%p, %d, %d, %d, %d)\n", dev
, left
, top
, right
, bottom
);
216 if(rect
.left
== rect
.right
|| rect
.top
== rect
.bottom
) return TRUE
;
218 if(defer_pen(pdev
) || defer_brush(pdev
))
219 return next
->funcs
->pRectangle( next
, left
, top
, right
, bottom
);
221 reset_dash_origin(pdev
);
223 /* 4 pts going anti-clockwise starting from top-right */
224 pts
[0].x
= pts
[3].x
= rect
.right
- 1;
225 pts
[0].y
= pts
[1].y
= rect
.top
;
226 pts
[1].x
= pts
[2].x
= rect
.left
;
227 pts
[2].y
= pts
[3].y
= rect
.bottom
- 1;
230 pdev
->pen_lines(pdev
, 5, pts
);
232 /* FIXME: Will need updating when we support wide pens */
239 brush_rects(pdev
, 1, &rect
);