xref: /reactos/win32ss/gdi/ntgdi/bitblt.c (revision 61cdd02d)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:        GNU GPL, See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:          ReactOS kernel
4c2c66affSColin Finck  * PURPOSE:          Bit blit functions
5c2c66affSColin Finck  * FILE:             win32ss/gdi/ntgdi/bitblt.c
6c2c66affSColin Finck  * PROGRAMER:        Unknown
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include <win32k.h>
10ce7836c6SDoug Lyons #define NDEBUG
11ce7836c6SDoug Lyons #include <debug.h>
12c2c66affSColin Finck DBG_DEFAULT_CHANNEL(GdiBlt);
13c2c66affSColin Finck 
14c2c66affSColin Finck BOOL APIENTRY
NtGdiAlphaBlend(HDC hDCDest,LONG XOriginDest,LONG YOriginDest,LONG WidthDest,LONG HeightDest,HDC hDCSrc,LONG XOriginSrc,LONG YOriginSrc,LONG WidthSrc,LONG HeightSrc,BLENDFUNCTION BlendFunc,HANDLE hcmXform)15c2c66affSColin Finck NtGdiAlphaBlend(
16c2c66affSColin Finck     HDC hDCDest,
17c2c66affSColin Finck     LONG XOriginDest,
18c2c66affSColin Finck     LONG YOriginDest,
19c2c66affSColin Finck     LONG WidthDest,
20c2c66affSColin Finck     LONG HeightDest,
21c2c66affSColin Finck     HDC hDCSrc,
22c2c66affSColin Finck     LONG XOriginSrc,
23c2c66affSColin Finck     LONG YOriginSrc,
24c2c66affSColin Finck     LONG WidthSrc,
25c2c66affSColin Finck     LONG HeightSrc,
26c2c66affSColin Finck     BLENDFUNCTION BlendFunc,
27c2c66affSColin Finck     HANDLE hcmXform)
28c2c66affSColin Finck {
29c2c66affSColin Finck     PDC DCDest;
30c2c66affSColin Finck     PDC DCSrc;
31c2c66affSColin Finck     HDC ahDC[2];
32c2c66affSColin Finck     PGDIOBJ apObj[2];
33c2c66affSColin Finck     SURFACE *BitmapDest, *BitmapSrc;
34c2c66affSColin Finck     RECTL DestRect, SourceRect;
35c2c66affSColin Finck     BOOL bResult;
36c2c66affSColin Finck     EXLATEOBJ exlo;
37c2c66affSColin Finck     BLENDOBJ BlendObj;
38c2c66affSColin Finck     BlendObj.BlendFunction = BlendFunc;
39c2c66affSColin Finck 
40c2c66affSColin Finck     if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
41c2c66affSColin Finck     {
42c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
43c2c66affSColin Finck         return FALSE;
44c2c66affSColin Finck     }
45c2c66affSColin Finck 
46c2c66affSColin Finck     if ((hDCDest == NULL) || (hDCSrc == NULL))
47c2c66affSColin Finck     {
48c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
49c2c66affSColin Finck         return FALSE;
50c2c66affSColin Finck     }
51c2c66affSColin Finck 
52c2c66affSColin Finck     TRACE("Locking DCs\n");
53c2c66affSColin Finck     ahDC[0] = hDCDest;
54c2c66affSColin Finck     ahDC[1] = hDCSrc ;
55c2c66affSColin Finck     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
56c2c66affSColin Finck     {
57c2c66affSColin Finck         WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
58c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
59c2c66affSColin Finck         return FALSE;
60c2c66affSColin Finck     }
61c2c66affSColin Finck     DCDest = apObj[0];
62c2c66affSColin Finck     DCSrc = apObj[1];
63c2c66affSColin Finck 
6496acfcb3SOleg Dubinskiy     if (DCSrc->dctype == DCTYPE_INFO || DCDest->dctype == DCTYPE_INFO)
65c2c66affSColin Finck     {
66c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
67c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCDest->BaseObject);
68c2c66affSColin Finck         /* Yes, Windows really returns TRUE in this case */
69c2c66affSColin Finck         return TRUE;
70c2c66affSColin Finck     }
71c2c66affSColin Finck 
72c2c66affSColin Finck     DestRect.left   = XOriginDest;
73c2c66affSColin Finck     DestRect.top    = YOriginDest;
74c2c66affSColin Finck     DestRect.right  = XOriginDest + WidthDest;
75c2c66affSColin Finck     DestRect.bottom = YOriginDest + HeightDest;
76c2c66affSColin Finck     IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
77c2c66affSColin Finck 
78c2c66affSColin Finck     DestRect.left   += DCDest->ptlDCOrig.x;
79c2c66affSColin Finck     DestRect.top    += DCDest->ptlDCOrig.y;
80c2c66affSColin Finck     DestRect.right  += DCDest->ptlDCOrig.x;
81c2c66affSColin Finck     DestRect.bottom += DCDest->ptlDCOrig.y;
82c2c66affSColin Finck 
83c2c66affSColin Finck     if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
84c2c66affSColin Finck     {
85c2c66affSColin Finck        IntUpdateBoundsRect(DCDest, &DestRect);
86c2c66affSColin Finck     }
87c2c66affSColin Finck 
88c2c66affSColin Finck     SourceRect.left   = XOriginSrc;
89c2c66affSColin Finck     SourceRect.top    = YOriginSrc;
90c2c66affSColin Finck     SourceRect.right  = XOriginSrc + WidthSrc;
91c2c66affSColin Finck     SourceRect.bottom = YOriginSrc + HeightSrc;
92c2c66affSColin Finck     IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
93c2c66affSColin Finck 
94c2c66affSColin Finck     SourceRect.left   += DCSrc->ptlDCOrig.x;
95c2c66affSColin Finck     SourceRect.top    += DCSrc->ptlDCOrig.y;
96c2c66affSColin Finck     SourceRect.right  += DCSrc->ptlDCOrig.x;
97c2c66affSColin Finck     SourceRect.bottom += DCSrc->ptlDCOrig.y;
98c2c66affSColin Finck 
99c2c66affSColin Finck     if (!DestRect.right ||
100c2c66affSColin Finck         !DestRect.bottom ||
101c2c66affSColin Finck         !SourceRect.right ||
102c2c66affSColin Finck         !SourceRect.bottom)
103c2c66affSColin Finck     {
104c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
105c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCDest->BaseObject);
106c2c66affSColin Finck         return TRUE;
107c2c66affSColin Finck     }
108c2c66affSColin Finck 
109c2c66affSColin Finck     /* Prepare DCs for blit */
110c2c66affSColin Finck     TRACE("Preparing DCs for blit\n");
111c2c66affSColin Finck     DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
112c2c66affSColin Finck 
113c2c66affSColin Finck     /* Determine surfaces to be used in the bitblt */
114c2c66affSColin Finck     BitmapDest = DCDest->dclevel.pSurface;
115c2c66affSColin Finck     if (!BitmapDest)
116c2c66affSColin Finck     {
117c2c66affSColin Finck         bResult = FALSE ;
118c2c66affSColin Finck         goto leave ;
119c2c66affSColin Finck     }
120c2c66affSColin Finck 
121c2c66affSColin Finck     BitmapSrc = DCSrc->dclevel.pSurface;
122c2c66affSColin Finck     if (!BitmapSrc)
123c2c66affSColin Finck     {
124c2c66affSColin Finck         bResult = FALSE;
125c2c66affSColin Finck         goto leave;
126c2c66affSColin Finck     }
127c2c66affSColin Finck 
128c2c66affSColin Finck     /* Create the XLATEOBJ. */
129c2c66affSColin Finck     EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
130c2c66affSColin Finck 
131c2c66affSColin Finck     /* Perform the alpha blend operation */
132c2c66affSColin Finck     TRACE("Performing the alpha blend\n");
133c2c66affSColin Finck     bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
134c2c66affSColin Finck                                &BitmapSrc->SurfObj,
135c2c66affSColin Finck                                (CLIPOBJ *)&DCDest->co,
136c2c66affSColin Finck                                &exlo.xlo,
137c2c66affSColin Finck                                &DestRect,
138c2c66affSColin Finck                                &SourceRect,
139c2c66affSColin Finck                                &BlendObj);
140c2c66affSColin Finck 
141c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
142c2c66affSColin Finck leave :
143c2c66affSColin Finck     TRACE("Finishing blit\n");
144c2c66affSColin Finck     DC_vFinishBlit(DCDest, DCSrc);
145c2c66affSColin Finck     GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
146c2c66affSColin Finck     GDIOBJ_vUnlockObject(&DCDest->BaseObject);
147c2c66affSColin Finck 
148c2c66affSColin Finck     return bResult;
149c2c66affSColin Finck }
150c2c66affSColin Finck 
151c2c66affSColin Finck BOOL APIENTRY
NtGdiBitBlt(HDC hDCDest,INT XDest,INT YDest,INT Width,INT Height,HDC hDCSrc,INT XSrc,INT YSrc,DWORD dwRop,IN DWORD crBackColor,IN FLONG fl)152c2c66affSColin Finck NtGdiBitBlt(
153c2c66affSColin Finck     HDC hDCDest,
154c2c66affSColin Finck     INT XDest,
155c2c66affSColin Finck     INT YDest,
156c2c66affSColin Finck     INT Width,
157c2c66affSColin Finck     INT Height,
158c2c66affSColin Finck     HDC hDCSrc,
159c2c66affSColin Finck     INT XSrc,
160c2c66affSColin Finck     INT YSrc,
161c2c66affSColin Finck     DWORD dwRop,
162c2c66affSColin Finck     IN DWORD crBackColor,
163c2c66affSColin Finck     IN FLONG fl)
164c2c66affSColin Finck {
165c2c66affSColin Finck 
166c2c66affSColin Finck     if (dwRop & CAPTUREBLT)
167c2c66affSColin Finck     {
168c2c66affSColin Finck        return NtGdiStretchBlt(hDCDest,
169c2c66affSColin Finck                               XDest,
170c2c66affSColin Finck                               YDest,
171c2c66affSColin Finck                               Width,
172c2c66affSColin Finck                               Height,
173c2c66affSColin Finck                               hDCSrc,
174c2c66affSColin Finck                               XSrc,
175c2c66affSColin Finck                               YSrc,
176c2c66affSColin Finck                               Width,
177c2c66affSColin Finck                               Height,
178c2c66affSColin Finck                               dwRop,
179c2c66affSColin Finck                               crBackColor);
180c2c66affSColin Finck     }
181c2c66affSColin Finck 
182c2c66affSColin Finck     dwRop = dwRop & ~(NOMIRRORBITMAP|CAPTUREBLT);
183c2c66affSColin Finck 
184c2c66affSColin Finck     /* Forward to NtGdiMaskBlt */
185c2c66affSColin Finck     // TODO: What's fl for? LOL not to send this to MaskBit!
186c2c66affSColin Finck     return NtGdiMaskBlt(hDCDest,
187c2c66affSColin Finck                         XDest,
188c2c66affSColin Finck                         YDest,
189c2c66affSColin Finck                         Width,
190c2c66affSColin Finck                         Height,
191c2c66affSColin Finck                         hDCSrc,
192c2c66affSColin Finck                         XSrc,
193c2c66affSColin Finck                         YSrc,
194c2c66affSColin Finck                         NULL,
195c2c66affSColin Finck                         0,
196c2c66affSColin Finck                         0,
197c2c66affSColin Finck                         MAKEROP4(dwRop, dwRop),
198c2c66affSColin Finck                         crBackColor);
199c2c66affSColin Finck }
200c2c66affSColin Finck 
201c2c66affSColin Finck BOOL APIENTRY
NtGdiTransparentBlt(HDC hdcDst,INT xDst,INT yDst,INT cxDst,INT cyDst,HDC hdcSrc,INT xSrc,INT ySrc,INT cxSrc,INT cySrc,COLORREF TransColor)202c2c66affSColin Finck NtGdiTransparentBlt(
203c2c66affSColin Finck     HDC hdcDst,
204c2c66affSColin Finck     INT xDst,
205c2c66affSColin Finck     INT yDst,
206c2c66affSColin Finck     INT cxDst,
207c2c66affSColin Finck     INT cyDst,
208c2c66affSColin Finck     HDC hdcSrc,
209c2c66affSColin Finck     INT xSrc,
210c2c66affSColin Finck     INT ySrc,
211c2c66affSColin Finck     INT cxSrc,
212c2c66affSColin Finck     INT cySrc,
213c2c66affSColin Finck     COLORREF TransColor)
214c2c66affSColin Finck {
215c2c66affSColin Finck     PDC DCDest, DCSrc;
216c2c66affSColin Finck     HDC ahDC[2];
217c2c66affSColin Finck     PGDIOBJ apObj[2];
218c2c66affSColin Finck     RECTL rcDest, rcSrc;
219c2c66affSColin Finck     SURFACE *BitmapDest, *BitmapSrc = NULL;
220c2c66affSColin Finck     ULONG TransparentColor = 0;
221c2c66affSColin Finck     BOOL Ret = FALSE;
222c2c66affSColin Finck     EXLATEOBJ exlo;
223c2c66affSColin Finck 
224c2c66affSColin Finck     if ((hdcDst == NULL) || (hdcSrc == NULL))
225c2c66affSColin Finck     {
226c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
227c2c66affSColin Finck         return FALSE;
228c2c66affSColin Finck     }
229c2c66affSColin Finck 
230c2c66affSColin Finck     TRACE("Locking DCs\n");
231c2c66affSColin Finck     ahDC[0] = hdcDst;
232c2c66affSColin Finck     ahDC[1] = hdcSrc ;
233c2c66affSColin Finck     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
234c2c66affSColin Finck     {
235c2c66affSColin Finck         WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
236c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
237c2c66affSColin Finck         return FALSE;
238c2c66affSColin Finck     }
239c2c66affSColin Finck     DCDest = apObj[0];
240c2c66affSColin Finck     DCSrc = apObj[1];
241c2c66affSColin Finck 
24296acfcb3SOleg Dubinskiy     if (DCSrc->dctype == DCTYPE_INFO || DCDest->dctype == DCTYPE_INFO)
243c2c66affSColin Finck     {
244c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
245c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCDest->BaseObject);
246c2c66affSColin Finck         /* Yes, Windows really returns TRUE in this case */
247c2c66affSColin Finck         return TRUE;
248c2c66affSColin Finck     }
249c2c66affSColin Finck 
250c2c66affSColin Finck     rcDest.left   = xDst;
251c2c66affSColin Finck     rcDest.top    = yDst;
252c2c66affSColin Finck     rcDest.right  = rcDest.left + cxDst;
253c2c66affSColin Finck     rcDest.bottom = rcDest.top + cyDst;
254c2c66affSColin Finck     IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
255c2c66affSColin Finck 
256c2c66affSColin Finck     rcDest.left   += DCDest->ptlDCOrig.x;
257c2c66affSColin Finck     rcDest.top    += DCDest->ptlDCOrig.y;
258c2c66affSColin Finck     rcDest.right  += DCDest->ptlDCOrig.x;
259c2c66affSColin Finck     rcDest.bottom += DCDest->ptlDCOrig.y;
260c2c66affSColin Finck 
261c2c66affSColin Finck     rcSrc.left   = xSrc;
262c2c66affSColin Finck     rcSrc.top    = ySrc;
263c2c66affSColin Finck     rcSrc.right  = rcSrc.left + cxSrc;
264c2c66affSColin Finck     rcSrc.bottom = rcSrc.top + cySrc;
265c2c66affSColin Finck     IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
266c2c66affSColin Finck 
267c2c66affSColin Finck     rcSrc.left   += DCSrc->ptlDCOrig.x;
268c2c66affSColin Finck     rcSrc.top    += DCSrc->ptlDCOrig.y;
269c2c66affSColin Finck     rcSrc.right  += DCSrc->ptlDCOrig.x;
270c2c66affSColin Finck     rcSrc.bottom += DCSrc->ptlDCOrig.y;
271c2c66affSColin Finck 
272c2c66affSColin Finck     if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
273c2c66affSColin Finck     {
274c2c66affSColin Finck        IntUpdateBoundsRect(DCDest, &rcDest);
275c2c66affSColin Finck     }
276c2c66affSColin Finck 
277c2c66affSColin Finck     /* Prepare for blit */
278c2c66affSColin Finck     DC_vPrepareDCsForBlit(DCDest, &rcDest, DCSrc, &rcSrc);
279c2c66affSColin Finck 
280c2c66affSColin Finck     BitmapDest = DCDest->dclevel.pSurface;
281c2c66affSColin Finck     if (!BitmapDest)
282c2c66affSColin Finck     {
283c2c66affSColin Finck         goto done;
284c2c66affSColin Finck     }
285c2c66affSColin Finck 
286c2c66affSColin Finck     BitmapSrc = DCSrc->dclevel.pSurface;
287c2c66affSColin Finck     if (!BitmapSrc)
288c2c66affSColin Finck     {
289c2c66affSColin Finck         goto done;
290c2c66affSColin Finck     }
291c2c66affSColin Finck 
292c2c66affSColin Finck     /* Translate Transparent (RGB) Color to the source palette */
293c2c66affSColin Finck     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0);
294c2c66affSColin Finck     TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
295c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
296c2c66affSColin Finck 
297c2c66affSColin Finck     EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
298c2c66affSColin Finck 
299c2c66affSColin Finck     Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
300c2c66affSColin Finck         (CLIPOBJ *)&DCDest->co, &exlo.xlo, &rcDest, &rcSrc,
301c2c66affSColin Finck         TransparentColor, 0);
302c2c66affSColin Finck 
303c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
304c2c66affSColin Finck 
305c2c66affSColin Finck done:
306c2c66affSColin Finck     DC_vFinishBlit(DCDest, DCSrc);
307c2c66affSColin Finck     GDIOBJ_vUnlockObject(&DCDest->BaseObject);
308c2c66affSColin Finck     GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
309c2c66affSColin Finck 
310c2c66affSColin Finck     return Ret;
311c2c66affSColin Finck }
312c2c66affSColin Finck 
313c2c66affSColin Finck BOOL APIENTRY
NtGdiMaskBlt(HDC hdcDest,INT nXDest,INT nYDest,INT nWidth,INT nHeight,HDC hdcSrc,INT nXSrc,INT nYSrc,HBITMAP hbmMask,INT xMask,INT yMask,DWORD dwRop4,IN DWORD crBackColor)314c2c66affSColin Finck NtGdiMaskBlt(
315c2c66affSColin Finck     HDC hdcDest,
316c2c66affSColin Finck     INT nXDest,
317c2c66affSColin Finck     INT nYDest,
318c2c66affSColin Finck     INT nWidth,
319c2c66affSColin Finck     INT nHeight,
320c2c66affSColin Finck     HDC hdcSrc,
321c2c66affSColin Finck     INT nXSrc,
322c2c66affSColin Finck     INT nYSrc,
323c2c66affSColin Finck     HBITMAP hbmMask,
324c2c66affSColin Finck     INT xMask,
325c2c66affSColin Finck     INT yMask,
326c2c66affSColin Finck     DWORD dwRop4,
327c2c66affSColin Finck     IN DWORD crBackColor)
328c2c66affSColin Finck {
329c2c66affSColin Finck     PDC DCDest;
330c2c66affSColin Finck     PDC DCSrc = NULL;
331c2c66affSColin Finck     HDC ahDC[2];
332c2c66affSColin Finck     PGDIOBJ apObj[2];
333c2c66affSColin Finck     PDC_ATTR pdcattr = NULL;
334c2c66affSColin Finck     SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL;
335c2c66affSColin Finck     RECTL DestRect, SourceRect;
336c2c66affSColin Finck     POINTL SourcePoint, MaskPoint;
337c2c66affSColin Finck     BOOL Status = FALSE;
338c2c66affSColin Finck     EXLATEOBJ exlo;
339c2c66affSColin Finck     XLATEOBJ *XlateObj = NULL;
340*61cdd02dSKatayama Hirofumi MZ     BOOL UsesSource, UsesPattern;
341c2c66affSColin Finck     ROP4 rop4;
342c2c66affSColin Finck 
343c2c66affSColin Finck     rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4);
344c2c66affSColin Finck 
345*61cdd02dSKatayama Hirofumi MZ     if (!hdcDest)
346c2c66affSColin Finck     {
347c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
348c2c66affSColin Finck         return FALSE;
349c2c66affSColin Finck     }
350c2c66affSColin Finck 
351*61cdd02dSKatayama Hirofumi MZ     UsesSource = ROP4_USES_SOURCE(rop4);
352*61cdd02dSKatayama Hirofumi MZ     UsesPattern = ROP4_USES_PATTERN(rop4);
353*61cdd02dSKatayama Hirofumi MZ     if (!hdcSrc && (UsesSource || UsesPattern))
354*61cdd02dSKatayama Hirofumi MZ         return FALSE;
355*61cdd02dSKatayama Hirofumi MZ 
356c2c66affSColin Finck     /* Check if we need a mask and have a mask bitmap */
357c2c66affSColin Finck     if (ROP4_USES_MASK(rop4) && (hbmMask != NULL))
358c2c66affSColin Finck     {
359c2c66affSColin Finck         /* Reference the mask bitmap */
360c2c66affSColin Finck         psurfMask = SURFACE_ShareLockSurface(hbmMask);
361c2c66affSColin Finck         if (psurfMask == NULL)
362c2c66affSColin Finck         {
363c2c66affSColin Finck             EngSetLastError(ERROR_INVALID_HANDLE);
364c2c66affSColin Finck             return FALSE;
365c2c66affSColin Finck         }
366c2c66affSColin Finck 
367c2c66affSColin Finck         /* Make sure the mask bitmap is 1 BPP */
368c2c66affSColin Finck         if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1)
369c2c66affSColin Finck         {
370c2c66affSColin Finck             SURFACE_ShareUnlockSurface(psurfMask);
371*61cdd02dSKatayama Hirofumi MZ             EngSetLastError(ERROR_INVALID_HANDLE);
372c2c66affSColin Finck             return FALSE;
373c2c66affSColin Finck         }
374c2c66affSColin Finck     }
375c2c66affSColin Finck     else
376c2c66affSColin Finck     {
377c2c66affSColin Finck         /* We use NULL, if we need a mask, the Eng function will take care of
378c2c66affSColin Finck            that and use the brushobject to get a mask */
379c2c66affSColin Finck         psurfMask = NULL;
380c2c66affSColin Finck     }
381c2c66affSColin Finck 
382c2c66affSColin Finck     MaskPoint.x = xMask;
383c2c66affSColin Finck     MaskPoint.y = yMask;
384c2c66affSColin Finck 
385c2c66affSColin Finck     /* Take care of source and destination bitmap */
386c2c66affSColin Finck     TRACE("Locking DCs\n");
387c2c66affSColin Finck     ahDC[0] = hdcDest;
388c2c66affSColin Finck     ahDC[1] = UsesSource ? hdcSrc : NULL;
389c2c66affSColin Finck     if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
390c2c66affSColin Finck     {
391c2c66affSColin Finck         WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiMaskBlt\n", hdcDest, hdcSrc);
392d9f8b8b0SJames Tabor         if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
393c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
394c2c66affSColin Finck         return FALSE;
395c2c66affSColin Finck     }
396c2c66affSColin Finck     DCDest = apObj[0];
397c2c66affSColin Finck     DCSrc = apObj[1];
398c2c66affSColin Finck 
399c2c66affSColin Finck     ASSERT(DCDest);
400c2c66affSColin Finck     if (NULL == DCDest)
401c2c66affSColin Finck     {
402c2c66affSColin Finck         if(DCSrc) DC_UnlockDc(DCSrc);
403c2c66affSColin Finck         WARN("Invalid destination dc handle (0x%p) passed to NtGdiMaskBlt\n", hdcDest);
404d9f8b8b0SJames Tabor         if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
405*61cdd02dSKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
406c2c66affSColin Finck         return FALSE;
407c2c66affSColin Finck     }
408c2c66affSColin Finck 
4095e93daa9SHermès Bélusca-Maïto     if (DCDest->dctype == DCTYPE_INFO)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         if(DCSrc) DC_UnlockDc(DCSrc);
412c2c66affSColin Finck         DC_UnlockDc(DCDest);
413c2c66affSColin Finck         /* Yes, Windows really returns TRUE in this case */
414d9f8b8b0SJames Tabor         if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
415c2c66affSColin Finck         return TRUE;
416c2c66affSColin Finck     }
417c2c66affSColin Finck 
418c2c66affSColin Finck     if (UsesSource)
419c2c66affSColin Finck     {
420c2c66affSColin Finck         ASSERT(DCSrc);
4215e93daa9SHermès Bélusca-Maïto         if (DCSrc->dctype == DCTYPE_INFO)
422c2c66affSColin Finck         {
423c2c66affSColin Finck             DC_UnlockDc(DCDest);
424c2c66affSColin Finck             DC_UnlockDc(DCSrc);
425c2c66affSColin Finck             /* Yes, Windows really returns TRUE in this case */
426d9f8b8b0SJames Tabor             if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
427c2c66affSColin Finck             return TRUE;
428c2c66affSColin Finck         }
429c2c66affSColin Finck     }
430c2c66affSColin Finck 
431c2c66affSColin Finck     pdcattr = DCDest->pdcattr;
432c2c66affSColin Finck 
433c2c66affSColin Finck     DestRect.left   = nXDest;
434c2c66affSColin Finck     DestRect.top    = nYDest;
435c2c66affSColin Finck     DestRect.right  = nXDest + nWidth;
436c2c66affSColin Finck     DestRect.bottom = nYDest + nHeight;
437c2c66affSColin Finck     IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
438c2c66affSColin Finck 
439c2c66affSColin Finck     DestRect.left   += DCDest->ptlDCOrig.x;
440c2c66affSColin Finck     DestRect.top    += DCDest->ptlDCOrig.y;
441c2c66affSColin Finck     DestRect.right  += DCDest->ptlDCOrig.x;
442c2c66affSColin Finck     DestRect.bottom += DCDest->ptlDCOrig.y;
443c2c66affSColin Finck 
444c2c66affSColin Finck     if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
445c2c66affSColin Finck     {
446c2c66affSColin Finck        IntUpdateBoundsRect(DCDest, &DestRect);
447c2c66affSColin Finck     }
448c2c66affSColin Finck 
449c2c66affSColin Finck     SourcePoint.x = nXSrc;
450c2c66affSColin Finck     SourcePoint.y = nYSrc;
451c2c66affSColin Finck 
452c2c66affSColin Finck     if (UsesSource)
453c2c66affSColin Finck     {
454c2c66affSColin Finck         IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
455c2c66affSColin Finck 
456c2c66affSColin Finck         SourcePoint.x += DCSrc->ptlDCOrig.x;
457c2c66affSColin Finck         SourcePoint.y += DCSrc->ptlDCOrig.y;
458c2c66affSColin Finck         /* Calculate Source Rect */
459c2c66affSColin Finck         SourceRect.left = SourcePoint.x;
460c2c66affSColin Finck         SourceRect.top = SourcePoint.y;
461c2c66affSColin Finck         SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
462c2c66affSColin Finck         SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
463c2c66affSColin Finck     }
464c2c66affSColin Finck     else
465c2c66affSColin Finck     {
466c2c66affSColin Finck         SourceRect.left = 0;
467c2c66affSColin Finck         SourceRect.top = 0;
468c2c66affSColin Finck         SourceRect.right = 0;
469c2c66affSColin Finck         SourceRect.bottom = 0;
470c2c66affSColin Finck     }
471c2c66affSColin Finck 
472c2c66affSColin Finck     /* Prepare blit */
473c2c66affSColin Finck     DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
474c2c66affSColin Finck 
475c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
476c2c66affSColin Finck         DC_vUpdateFillBrush(DCDest);
477c2c66affSColin Finck 
478c2c66affSColin Finck     /* Determine surfaces to be used in the bitblt */
479c2c66affSColin Finck     BitmapDest = DCDest->dclevel.pSurface;
480c2c66affSColin Finck     if (!BitmapDest)
481c2c66affSColin Finck         goto cleanup;
482c2c66affSColin Finck 
483c2c66affSColin Finck     if (UsesSource)
484c2c66affSColin Finck     {
485c2c66affSColin Finck         BitmapSrc = DCSrc->dclevel.pSurface;
486c2c66affSColin Finck         if (!BitmapSrc)
487c2c66affSColin Finck             goto cleanup;
488c2c66affSColin Finck 
489c2c66affSColin Finck         /* Create the XLATEOBJ. */
490c2c66affSColin Finck         EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
491c2c66affSColin Finck         XlateObj = &exlo.xlo;
492c2c66affSColin Finck     }
493c2c66affSColin Finck 
494ce7836c6SDoug Lyons     DPRINT("DestRect: (%d,%d)-(%d,%d) and SourcePoint is (%d,%d)\n",
495ce7836c6SDoug Lyons         DestRect.left, DestRect.top, DestRect.right, DestRect.bottom,
496ce7836c6SDoug Lyons         SourcePoint.x, SourcePoint.y);
497ce7836c6SDoug Lyons 
498ce7836c6SDoug Lyons     DPRINT("nWidth is '%d' and nHeight is '%d'.\n", nWidth, nHeight);
499ce7836c6SDoug Lyons 
500ce7836c6SDoug Lyons     /* Fix BitBlt so that it will not flip left to right */
501ce7836c6SDoug Lyons     if ((DestRect.left > DestRect.right) && (nWidth < 0))
502ce7836c6SDoug Lyons     {
503ce7836c6SDoug Lyons         SourcePoint.x += nWidth;
504ce7836c6SDoug Lyons         nWidth = -nWidth;
505ce7836c6SDoug Lyons     }
506ce7836c6SDoug Lyons 
507ce7836c6SDoug Lyons     /* Fix BitBlt so that it will not flip top to bottom */
508ce7836c6SDoug Lyons     if ((DestRect.top > DestRect.bottom) && (nHeight < 0))
509ce7836c6SDoug Lyons     {
510ce7836c6SDoug Lyons         SourcePoint.y += nHeight;
511ce7836c6SDoug Lyons         nHeight = -nHeight;
512ce7836c6SDoug Lyons     }
513ce7836c6SDoug Lyons 
514ce7836c6SDoug Lyons     /* Make Well Ordered so that we don't flip either way */
515ce7836c6SDoug Lyons     RECTL_vMakeWellOrdered(&DestRect);
516ce7836c6SDoug Lyons 
517c2c66affSColin Finck     /* Perform the bitblt operation */
518c2c66affSColin Finck     Status = IntEngBitBlt(&BitmapDest->SurfObj,
519c2c66affSColin Finck                           BitmapSrc ? &BitmapSrc->SurfObj : NULL,
520c2c66affSColin Finck                           psurfMask ? &psurfMask->SurfObj : NULL,
521c2c66affSColin Finck                           (CLIPOBJ *)&DCDest->co,
522c2c66affSColin Finck                           XlateObj,
523c2c66affSColin Finck                           &DestRect,
524c2c66affSColin Finck                           &SourcePoint,
525c2c66affSColin Finck                           &MaskPoint,
526c2c66affSColin Finck                           &DCDest->eboFill.BrushObject,
527c2c66affSColin Finck                           &DCDest->dclevel.pbrFill->ptOrigin,
528c2c66affSColin Finck                           rop4);
529c2c66affSColin Finck 
530c2c66affSColin Finck     if (UsesSource)
531c2c66affSColin Finck         EXLATEOBJ_vCleanup(&exlo);
532c2c66affSColin Finck cleanup:
533c2c66affSColin Finck     DC_vFinishBlit(DCDest, DCSrc);
534c2c66affSColin Finck     if (UsesSource)
535c2c66affSColin Finck     {
536c2c66affSColin Finck         DC_UnlockDc(DCSrc);
537c2c66affSColin Finck     }
538c2c66affSColin Finck     DC_UnlockDc(DCDest);
539c2c66affSColin Finck     if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
540c2c66affSColin Finck 
541*61cdd02dSKatayama Hirofumi MZ     if (!Status)
542*61cdd02dSKatayama Hirofumi MZ         EngSetLastError(ERROR_INVALID_PARAMETER);
543*61cdd02dSKatayama Hirofumi MZ 
544c2c66affSColin Finck     return Status;
545c2c66affSColin Finck }
546c2c66affSColin Finck 
547c2c66affSColin Finck BOOL
548c2c66affSColin Finck APIENTRY
NtGdiPlgBlt(IN HDC hdcTrg,IN LPPOINT pptlTrg,IN HDC hdcSrc,IN INT xSrc,IN INT ySrc,IN INT cxSrc,IN INT cySrc,IN HBITMAP hbmMask,IN INT xMask,IN INT yMask,IN DWORD crBackColor)549c2c66affSColin Finck NtGdiPlgBlt(
550c2c66affSColin Finck     IN HDC hdcTrg,
551c2c66affSColin Finck     IN LPPOINT pptlTrg,
552c2c66affSColin Finck     IN HDC hdcSrc,
553c2c66affSColin Finck     IN INT xSrc,
554c2c66affSColin Finck     IN INT ySrc,
555c2c66affSColin Finck     IN INT cxSrc,
556c2c66affSColin Finck     IN INT cySrc,
557c2c66affSColin Finck     IN HBITMAP hbmMask,
558c2c66affSColin Finck     IN INT xMask,
559c2c66affSColin Finck     IN INT yMask,
560c2c66affSColin Finck     IN DWORD crBackColor)
561c2c66affSColin Finck {
562c2c66affSColin Finck     FIXME("NtGdiPlgBlt: unimplemented.\n");
563c2c66affSColin Finck     return FALSE;
564c2c66affSColin Finck }
565c2c66affSColin Finck 
566c2c66affSColin Finck BOOL
567c2c66affSColin Finck NTAPI
GreStretchBltMask(HDC hDCDest,INT XOriginDest,INT YOriginDest,INT WidthDest,INT HeightDest,HDC hDCSrc,INT XOriginSrc,INT YOriginSrc,INT WidthSrc,INT HeightSrc,DWORD dwRop4,IN DWORD dwBackColor,HDC hDCMask,INT XOriginMask,INT YOriginMask)568c2c66affSColin Finck GreStretchBltMask(
569c2c66affSColin Finck     HDC hDCDest,
570c2c66affSColin Finck     INT XOriginDest,
571c2c66affSColin Finck     INT YOriginDest,
572c2c66affSColin Finck     INT WidthDest,
573c2c66affSColin Finck     INT HeightDest,
574c2c66affSColin Finck     HDC hDCSrc,
575c2c66affSColin Finck     INT XOriginSrc,
576c2c66affSColin Finck     INT YOriginSrc,
577c2c66affSColin Finck     INT WidthSrc,
578c2c66affSColin Finck     INT HeightSrc,
579c2c66affSColin Finck     DWORD dwRop4,
580c2c66affSColin Finck     IN DWORD dwBackColor,
581c2c66affSColin Finck     HDC hDCMask,
582c2c66affSColin Finck     INT XOriginMask,
583c2c66affSColin Finck     INT YOriginMask)
584c2c66affSColin Finck {
585c2c66affSColin Finck     PDC DCDest;
586c2c66affSColin Finck     PDC DCSrc  = NULL;
587c2c66affSColin Finck     PDC DCMask = NULL;
588c2c66affSColin Finck     HDC ahDC[3];
589c2c66affSColin Finck     PGDIOBJ apObj[3];
590c2c66affSColin Finck     PDC_ATTR pdcattr;
591c2c66affSColin Finck     SURFACE *BitmapDest, *BitmapSrc = NULL;
592c2c66affSColin Finck     SURFACE *BitmapMask = NULL;
593c2c66affSColin Finck     RECTL DestRect;
594c2c66affSColin Finck     RECTL SourceRect;
595c2c66affSColin Finck     POINTL MaskPoint;
596c2c66affSColin Finck     BOOL Status = FALSE;
597c2c66affSColin Finck     EXLATEOBJ exlo;
598c2c66affSColin Finck     XLATEOBJ *XlateObj = NULL;
599c2c66affSColin Finck     POINTL BrushOrigin;
600c2c66affSColin Finck     BOOL UsesSource;
601c2c66affSColin Finck     BOOL UsesMask;
602c2c66affSColin Finck     ROP4 rop4;
603ce7836c6SDoug Lyons     BOOL Case0000, Case0101, Case1010, CaseExcept;
604c2c66affSColin Finck 
605c2c66affSColin Finck     rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4);
606c2c66affSColin Finck 
607c2c66affSColin Finck     UsesSource = ROP4_USES_SOURCE(rop4);
608c2c66affSColin Finck     UsesMask = ROP4_USES_MASK(rop4);
609c2c66affSColin Finck 
610c2c66affSColin Finck     if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
611c2c66affSColin Finck     {
612c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
613c2c66affSColin Finck         return TRUE;
614c2c66affSColin Finck     }
615c2c66affSColin Finck 
616c2c66affSColin Finck     if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask))
617c2c66affSColin Finck     {
618c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
619c2c66affSColin Finck         return FALSE;
620c2c66affSColin Finck     }
621c2c66affSColin Finck 
622c2c66affSColin Finck     ahDC[0] = hDCDest;
623c2c66affSColin Finck     ahDC[1] = UsesSource ? hDCSrc : NULL;
624c2c66affSColin Finck     ahDC[2] = UsesMask ? hDCMask : NULL;
625c2c66affSColin Finck     if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
626c2c66affSColin Finck     {
627c2c66affSColin Finck         WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc);
628c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
629c2c66affSColin Finck         return FALSE;
630c2c66affSColin Finck     }
631c2c66affSColin Finck     DCDest = apObj[0];
632c2c66affSColin Finck     DCSrc = apObj[1];
633c2c66affSColin Finck     DCMask = apObj[2];
634c2c66affSColin Finck 
6355e93daa9SHermès Bélusca-Maïto     if (DCDest->dctype == DCTYPE_INFO)
636c2c66affSColin Finck     {
637c2c66affSColin Finck         if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
638c2c66affSColin Finck         if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
639c2c66affSColin Finck         GDIOBJ_vUnlockObject(&DCDest->BaseObject);
640c2c66affSColin Finck         /* Yes, Windows really returns TRUE in this case */
641c2c66affSColin Finck         return TRUE;
642c2c66affSColin Finck     }
643c2c66affSColin Finck 
644c2c66affSColin Finck     if (UsesSource)
645c2c66affSColin Finck     {
6465e93daa9SHermès Bélusca-Maïto         if (DCSrc->dctype == DCTYPE_INFO)
647c2c66affSColin Finck         {
648c2c66affSColin Finck             GDIOBJ_vUnlockObject(&DCDest->BaseObject);
649c2c66affSColin Finck             GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
650c2c66affSColin Finck             if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
651c2c66affSColin Finck             /* Yes, Windows really returns TRUE in this case */
652c2c66affSColin Finck             return TRUE;
653c2c66affSColin Finck         }
654c2c66affSColin Finck     }
655c2c66affSColin Finck 
656ce7836c6SDoug Lyons 
657ce7836c6SDoug Lyons     Case0000 = ((WidthDest < 0) && (HeightDest < 0) && (WidthSrc < 0) && (HeightSrc < 0));
658ce7836c6SDoug Lyons     Case0101 = ((WidthDest < 0) && (HeightDest > 0) && (WidthSrc < 0) && (HeightSrc > 0));
659ce7836c6SDoug Lyons     Case1010 = ((WidthDest > 0) && (HeightDest < 0) && (WidthSrc > 0) && (HeightSrc < 0));
660ce7836c6SDoug Lyons     CaseExcept = (Case0000 || Case0101 || Case1010);
661ce7836c6SDoug Lyons 
662c2c66affSColin Finck     pdcattr = DCDest->pdcattr;
663c2c66affSColin Finck 
664c2c66affSColin Finck     DestRect.left   = XOriginDest;
665c2c66affSColin Finck     DestRect.top    = YOriginDest;
666c2c66affSColin Finck     DestRect.right  = XOriginDest+WidthDest;
667c2c66affSColin Finck     DestRect.bottom = YOriginDest+HeightDest;
668ce7836c6SDoug Lyons 
669ce7836c6SDoug Lyons     /* Account for possible negative span values */
670ce7836c6SDoug Lyons     if ((WidthDest < 0) && !CaseExcept)
671ce7836c6SDoug Lyons     {
672ce7836c6SDoug Lyons         DestRect.left++;
673ce7836c6SDoug Lyons         DestRect.right++;
674ce7836c6SDoug Lyons     }
675ce7836c6SDoug Lyons     if ((HeightDest < 0) && !CaseExcept)
676ce7836c6SDoug Lyons     {
677ce7836c6SDoug Lyons         DestRect.top++;
678ce7836c6SDoug Lyons         DestRect.bottom++;
679ce7836c6SDoug Lyons     }
680ce7836c6SDoug Lyons 
681c2c66affSColin Finck     IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
682c2c66affSColin Finck 
683c2c66affSColin Finck     DestRect.left   += DCDest->ptlDCOrig.x;
684c2c66affSColin Finck     DestRect.top    += DCDest->ptlDCOrig.y;
685c2c66affSColin Finck     DestRect.right  += DCDest->ptlDCOrig.x;
686c2c66affSColin Finck     DestRect.bottom += DCDest->ptlDCOrig.y;
687c2c66affSColin Finck 
688c2c66affSColin Finck     if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
689c2c66affSColin Finck     {
690c2c66affSColin Finck        IntUpdateBoundsRect(DCDest, &DestRect);
691c2c66affSColin Finck     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     SourceRect.left   = XOriginSrc;
694c2c66affSColin Finck     SourceRect.top    = YOriginSrc;
695c2c66affSColin Finck     SourceRect.right  = XOriginSrc+WidthSrc;
696c2c66affSColin Finck     SourceRect.bottom = YOriginSrc+HeightSrc;
697c2c66affSColin Finck 
698ce7836c6SDoug Lyons     /* Account for possible negative span values */
699ce7836c6SDoug Lyons     if ((WidthSrc < 0) && !CaseExcept)
700ce7836c6SDoug Lyons     {
701ce7836c6SDoug Lyons         SourceRect.left++;
702ce7836c6SDoug Lyons         SourceRect.right++;
703ce7836c6SDoug Lyons     }
704ce7836c6SDoug Lyons     if ((HeightSrc < 0) && !CaseExcept)
705ce7836c6SDoug Lyons     {
706ce7836c6SDoug Lyons         SourceRect.top++;
707ce7836c6SDoug Lyons         SourceRect.bottom++;
708ce7836c6SDoug Lyons     }
709ce7836c6SDoug Lyons 
710c2c66affSColin Finck     if (UsesSource)
711c2c66affSColin Finck     {
712c2c66affSColin Finck         IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
713c2c66affSColin Finck 
714c2c66affSColin Finck         SourceRect.left   += DCSrc->ptlDCOrig.x;
715c2c66affSColin Finck         SourceRect.top    += DCSrc->ptlDCOrig.y;
716c2c66affSColin Finck         SourceRect.right  += DCSrc->ptlDCOrig.x;
717c2c66affSColin Finck         SourceRect.bottom += DCSrc->ptlDCOrig.y;
718c2c66affSColin Finck     }
719c2c66affSColin Finck 
720c2c66affSColin Finck     BrushOrigin.x = 0;
721c2c66affSColin Finck     BrushOrigin.y = 0;
722c2c66affSColin Finck 
723c2c66affSColin Finck     /* Only prepare Source and Dest, hdcMask represents a DIB */
724c2c66affSColin Finck     DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);
725c2c66affSColin Finck 
726c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
727c2c66affSColin Finck         DC_vUpdateFillBrush(DCDest);
728c2c66affSColin Finck 
729c2c66affSColin Finck     /* Determine surfaces to be used in the bitblt */
730c2c66affSColin Finck     BitmapDest = DCDest->dclevel.pSurface;
731c2c66affSColin Finck     if (BitmapDest == NULL)
732c2c66affSColin Finck         goto failed;
733c2c66affSColin Finck     if (UsesSource)
734c2c66affSColin Finck     {
735c2c66affSColin Finck         BitmapSrc = DCSrc->dclevel.pSurface;
736c2c66affSColin Finck         if (BitmapSrc == NULL)
737c2c66affSColin Finck             goto failed;
738c2c66affSColin Finck 
739c2c66affSColin Finck         /* Create the XLATEOBJ. */
740c2c66affSColin Finck         EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
741c2c66affSColin Finck         XlateObj = &exlo.xlo;
742c2c66affSColin Finck     }
743c2c66affSColin Finck 
744c2c66affSColin Finck     /* Offset the brush */
745c2c66affSColin Finck     BrushOrigin.x += DCDest->ptlDCOrig.x;
746c2c66affSColin Finck     BrushOrigin.y += DCDest->ptlDCOrig.y;
747c2c66affSColin Finck 
748c2c66affSColin Finck     /* Make mask surface for source surface */
749c2c66affSColin Finck     if (BitmapSrc && DCMask)
750c2c66affSColin Finck     {
751c2c66affSColin Finck         BitmapMask = DCMask->dclevel.pSurface;
752c2c66affSColin Finck         if (BitmapMask &&
753c2c66affSColin Finck             (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
754c2c66affSColin Finck              BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
755c2c66affSColin Finck         {
756c2c66affSColin Finck             WARN("%dx%d mask is smaller than %dx%d bitmap\n",
757c2c66affSColin Finck                     BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
758c2c66affSColin Finck                     WidthSrc, HeightSrc);
759c2c66affSColin Finck             EXLATEOBJ_vCleanup(&exlo);
760c2c66affSColin Finck             goto failed;
761c2c66affSColin Finck         }
762c2c66affSColin Finck         /* Create mask offset point */
763c2c66affSColin Finck         MaskPoint.x = XOriginMask;
764c2c66affSColin Finck         MaskPoint.y = YOriginMask;
765c2c66affSColin Finck         IntLPtoDP(DCMask, &MaskPoint, 1);
766c2c66affSColin Finck         MaskPoint.x += DCMask->ptlDCOrig.x;
767c2c66affSColin Finck         MaskPoint.y += DCMask->ptlDCOrig.y;
768c2c66affSColin Finck     }
769c2c66affSColin Finck 
770ce7836c6SDoug Lyons     DPRINT("Calling IntEngStrethBlt SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d).\n",
771ce7836c6SDoug Lyons            SourceRect.left, SourceRect.top, SourceRect.right, SourceRect.bottom,
772ce7836c6SDoug Lyons            DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
773ce7836c6SDoug Lyons 
774c2c66affSColin Finck     /* Perform the bitblt operation */
775c2c66affSColin Finck     Status = IntEngStretchBlt(&BitmapDest->SurfObj,
776c2c66affSColin Finck                               BitmapSrc ? &BitmapSrc->SurfObj : NULL,
777c2c66affSColin Finck                               BitmapMask ? &BitmapMask->SurfObj : NULL,
778c2c66affSColin Finck                               (CLIPOBJ *)&DCDest->co,
779c2c66affSColin Finck                               XlateObj,
780c2c66affSColin Finck                               &DCDest->dclevel.ca,
781c2c66affSColin Finck                               &DestRect,
782c2c66affSColin Finck                               &SourceRect,
783c2c66affSColin Finck                               BitmapMask ? &MaskPoint : NULL,
784c2c66affSColin Finck                               &DCDest->eboFill.BrushObject,
785c2c66affSColin Finck                               &BrushOrigin,
786c2c66affSColin Finck                               rop4);
787c2c66affSColin Finck     if (UsesSource)
788c2c66affSColin Finck     {
789c2c66affSColin Finck         EXLATEOBJ_vCleanup(&exlo);
790c2c66affSColin Finck     }
791c2c66affSColin Finck 
792c2c66affSColin Finck failed:
793c2c66affSColin Finck     DC_vFinishBlit(DCDest, DCSrc);
794c2c66affSColin Finck     if (UsesSource)
795c2c66affSColin Finck     {
796c2c66affSColin Finck         DC_UnlockDc(DCSrc);
797c2c66affSColin Finck     }
798c2c66affSColin Finck     if (DCMask)
799c2c66affSColin Finck     {
800c2c66affSColin Finck         DC_UnlockDc(DCMask);
801c2c66affSColin Finck     }
802c2c66affSColin Finck     DC_UnlockDc(DCDest);
803c2c66affSColin Finck 
804c2c66affSColin Finck     return Status;
805c2c66affSColin Finck }
806c2c66affSColin Finck 
807c2c66affSColin Finck 
808c2c66affSColin Finck BOOL APIENTRY
NtGdiStretchBlt(HDC hDCDest,INT XOriginDest,INT YOriginDest,INT WidthDest,INT HeightDest,HDC hDCSrc,INT XOriginSrc,INT YOriginSrc,INT WidthSrc,INT HeightSrc,DWORD dwRop3,IN DWORD dwBackColor)809c2c66affSColin Finck NtGdiStretchBlt(
810c2c66affSColin Finck     HDC hDCDest,
811c2c66affSColin Finck     INT XOriginDest,
812c2c66affSColin Finck     INT YOriginDest,
813c2c66affSColin Finck     INT WidthDest,
814c2c66affSColin Finck     INT HeightDest,
815c2c66affSColin Finck     HDC hDCSrc,
816c2c66affSColin Finck     INT XOriginSrc,
817c2c66affSColin Finck     INT YOriginSrc,
818c2c66affSColin Finck     INT WidthSrc,
819c2c66affSColin Finck     INT HeightSrc,
820c2c66affSColin Finck     DWORD dwRop3,
821c2c66affSColin Finck     IN DWORD dwBackColor)
822c2c66affSColin Finck {
823c2c66affSColin Finck     dwRop3 = dwRop3 & ~(NOMIRRORBITMAP|CAPTUREBLT);
824c2c66affSColin Finck 
825c2c66affSColin Finck     return GreStretchBltMask(
826c2c66affSColin Finck                 hDCDest,
827c2c66affSColin Finck                 XOriginDest,
828c2c66affSColin Finck                 YOriginDest,
829c2c66affSColin Finck                 WidthDest,
830c2c66affSColin Finck                 HeightDest,
831c2c66affSColin Finck                 hDCSrc,
832c2c66affSColin Finck                 XOriginSrc,
833c2c66affSColin Finck                 YOriginSrc,
834c2c66affSColin Finck                 WidthSrc,
835c2c66affSColin Finck                 HeightSrc,
836c2c66affSColin Finck                 MAKEROP4(dwRop3 & 0xFF0000, dwRop3),
837c2c66affSColin Finck                 dwBackColor,
838c2c66affSColin Finck                 NULL,
839c2c66affSColin Finck                 0,
840c2c66affSColin Finck                 0);
841c2c66affSColin Finck }
842c2c66affSColin Finck 
843c2c66affSColin Finck 
844c2c66affSColin Finck BOOL FASTCALL
IntPatBlt(PDC pdc,INT XLeft,INT YLeft,INT Width,INT Height,DWORD dwRop3,PEBRUSHOBJ pebo)845c2c66affSColin Finck IntPatBlt(
846c2c66affSColin Finck     PDC pdc,
847c2c66affSColin Finck     INT XLeft,
848c2c66affSColin Finck     INT YLeft,
849c2c66affSColin Finck     INT Width,
850c2c66affSColin Finck     INT Height,
851c2c66affSColin Finck     DWORD dwRop3,
852c2c66affSColin Finck     PEBRUSHOBJ pebo)
853c2c66affSColin Finck {
854c2c66affSColin Finck     RECTL DestRect;
855c2c66affSColin Finck     SURFACE *psurf;
856c2c66affSColin Finck     POINTL BrushOrigin;
857c2c66affSColin Finck     BOOL ret;
858c2c66affSColin Finck     PBRUSH pbrush;
859c2c66affSColin Finck 
860c2c66affSColin Finck     ASSERT(pebo);
861c2c66affSColin Finck     pbrush = pebo->pbrush;
862c2c66affSColin Finck     ASSERT(pbrush);
863c2c66affSColin Finck 
864c2c66affSColin Finck     if (pbrush->flAttrs & BR_IS_NULL)
865c2c66affSColin Finck     {
866c2c66affSColin Finck         return TRUE;
867c2c66affSColin Finck     }
868c2c66affSColin Finck 
8690bfa0cd0SKatayama Hirofumi MZ     if (Width >= 0)
870c2c66affSColin Finck     {
871c2c66affSColin Finck         DestRect.left = XLeft;
872c2c66affSColin Finck         DestRect.right = XLeft + Width;
873c2c66affSColin Finck     }
874c2c66affSColin Finck     else
875c2c66affSColin Finck     {
8760bfa0cd0SKatayama Hirofumi MZ         DestRect.left = XLeft + Width;
8770bfa0cd0SKatayama Hirofumi MZ         DestRect.right = XLeft;
878c2c66affSColin Finck     }
879c2c66affSColin Finck 
8800bfa0cd0SKatayama Hirofumi MZ     if (Height >= 0)
881c2c66affSColin Finck     {
882c2c66affSColin Finck         DestRect.top = YLeft;
883c2c66affSColin Finck         DestRect.bottom = YLeft + Height;
884c2c66affSColin Finck     }
885c2c66affSColin Finck     else
886c2c66affSColin Finck     {
8870bfa0cd0SKatayama Hirofumi MZ         DestRect.top = YLeft + Height;
8880bfa0cd0SKatayama Hirofumi MZ         DestRect.bottom = YLeft;
889c2c66affSColin Finck     }
890c2c66affSColin Finck 
891c2c66affSColin Finck     IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
892c2c66affSColin Finck 
893c2c66affSColin Finck     DestRect.left   += pdc->ptlDCOrig.x;
894c2c66affSColin Finck     DestRect.top    += pdc->ptlDCOrig.y;
895c2c66affSColin Finck     DestRect.right  += pdc->ptlDCOrig.x;
896c2c66affSColin Finck     DestRect.bottom += pdc->ptlDCOrig.y;
897c2c66affSColin Finck 
898c2c66affSColin Finck     if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
899c2c66affSColin Finck     {
900c2c66affSColin Finck        IntUpdateBoundsRect(pdc, &DestRect);
901c2c66affSColin Finck     }
902c2c66affSColin Finck 
903c2c66affSColin Finck #ifdef _USE_DIBLIB_
904c2c66affSColin Finck     BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft;
905c2c66affSColin Finck     BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft;
906c2c66affSColin Finck #else
907c2c66affSColin Finck     BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
908c2c66affSColin Finck     BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
909c2c66affSColin Finck #endif
910c2c66affSColin Finck 
911c2c66affSColin Finck     DC_vPrepareDCsForBlit(pdc, &DestRect, NULL, NULL);
912c2c66affSColin Finck 
913c2c66affSColin Finck     psurf = pdc->dclevel.pSurface;
914c2c66affSColin Finck 
915c2c66affSColin Finck     ret = IntEngBitBlt(&psurf->SurfObj,
916c2c66affSColin Finck                        NULL,
917c2c66affSColin Finck                        NULL,
918c2c66affSColin Finck                        (CLIPOBJ *)&pdc->co,
919c2c66affSColin Finck                        NULL,
920c2c66affSColin Finck                        &DestRect,
921c2c66affSColin Finck                        NULL,
922c2c66affSColin Finck                        NULL,
923c2c66affSColin Finck                        &pebo->BrushObject,
924c2c66affSColin Finck                        &BrushOrigin,
925c2c66affSColin Finck                        WIN32_ROP3_TO_ENG_ROP4(dwRop3));
926c2c66affSColin Finck 
927c2c66affSColin Finck     DC_vFinishBlit(pdc, NULL);
928c2c66affSColin Finck 
929c2c66affSColin Finck     return ret;
930c2c66affSColin Finck }
931c2c66affSColin Finck 
932c2c66affSColin Finck BOOL FASTCALL
IntGdiPolyPatBlt(HDC hDC,DWORD dwRop,PPATRECT pRects,INT cRects,ULONG Reserved)933c2c66affSColin Finck IntGdiPolyPatBlt(
934c2c66affSColin Finck     HDC hDC,
935c2c66affSColin Finck     DWORD dwRop,
936c2c66affSColin Finck     PPATRECT pRects,
937c2c66affSColin Finck     INT cRects,
938c2c66affSColin Finck     ULONG Reserved)
939c2c66affSColin Finck {
940c2c66affSColin Finck     INT i;
941c2c66affSColin Finck     PBRUSH pbrush;
942c2c66affSColin Finck     PDC pdc;
943c2c66affSColin Finck     EBRUSHOBJ eboFill;
944c2c66affSColin Finck 
945c2c66affSColin Finck     pdc = DC_LockDc(hDC);
946c2c66affSColin Finck     if (!pdc)
947c2c66affSColin Finck     {
948c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
949c2c66affSColin Finck         return FALSE;
950c2c66affSColin Finck     }
951c2c66affSColin Finck 
9525e93daa9SHermès Bélusca-Maïto     if (pdc->dctype == DCTYPE_INFO)
953c2c66affSColin Finck     {
954c2c66affSColin Finck         DC_UnlockDc(pdc);
955c2c66affSColin Finck         /* Yes, Windows really returns TRUE in this case */
956c2c66affSColin Finck         return TRUE;
957c2c66affSColin Finck     }
958c2c66affSColin Finck 
959c2c66affSColin Finck     for (i = 0; i < cRects; i++)
960c2c66affSColin Finck     {
961c2c66affSColin Finck         pbrush = BRUSH_ShareLockBrush(pRects->hBrush);
962c2c66affSColin Finck 
963c2c66affSColin Finck         /* Check if we could lock the brush */
964c2c66affSColin Finck         if (pbrush != NULL)
965c2c66affSColin Finck         {
966c2c66affSColin Finck             /* Initialize a brush object */
967c2c66affSColin Finck             EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc);
968c2c66affSColin Finck 
969c2c66affSColin Finck             IntPatBlt(
970c2c66affSColin Finck                 pdc,
971c2c66affSColin Finck                 pRects->r.left,
972c2c66affSColin Finck                 pRects->r.top,
973c2c66affSColin Finck                 pRects->r.right,
974c2c66affSColin Finck                 pRects->r.bottom,
975c2c66affSColin Finck                 dwRop,
976c2c66affSColin Finck                 &eboFill);
977c2c66affSColin Finck 
978c2c66affSColin Finck             /* Cleanup the brush object and unlock the brush */
979c2c66affSColin Finck             EBRUSHOBJ_vCleanup(&eboFill);
980c2c66affSColin Finck             BRUSH_ShareUnlockBrush(pbrush);
981c2c66affSColin Finck         }
982c2c66affSColin Finck         pRects++;
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     DC_UnlockDc(pdc);
986c2c66affSColin Finck 
987c2c66affSColin Finck     return TRUE;
988c2c66affSColin Finck }
989c2c66affSColin Finck 
990c2c66affSColin Finck BOOL
991c2c66affSColin Finck APIENTRY
NtGdiPatBlt(_In_ HDC hdcDest,_In_ INT x,_In_ INT y,_In_ INT cx,_In_ INT cy,_In_ DWORD dwRop)992c2c66affSColin Finck NtGdiPatBlt(
993c2c66affSColin Finck     _In_ HDC hdcDest,
994c2c66affSColin Finck     _In_ INT x,
995c2c66affSColin Finck     _In_ INT y,
996c2c66affSColin Finck     _In_ INT cx,
997c2c66affSColin Finck     _In_ INT cy,
998c2c66affSColin Finck     _In_ DWORD dwRop)
999c2c66affSColin Finck {
1000c2c66affSColin Finck     BOOL bResult;
1001c2c66affSColin Finck     PDC pdc;
1002c2c66affSColin Finck 
1003c2c66affSColin Finck     /* Convert the ROP3 to a ROP4 */
1004c2c66affSColin Finck     dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop);
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     /* Check if the rop uses a source */
1007c2c66affSColin Finck     if (WIN32_ROP4_USES_SOURCE(dwRop))
1008c2c66affSColin Finck     {
1009c2c66affSColin Finck         /* This is not possible */
1010c2c66affSColin Finck         return FALSE;
1011c2c66affSColin Finck     }
1012c2c66affSColin Finck 
1013c2c66affSColin Finck     /* Lock the DC */
1014c2c66affSColin Finck     pdc = DC_LockDc(hdcDest);
1015c2c66affSColin Finck     if (pdc == NULL)
1016c2c66affSColin Finck     {
1017c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1018c2c66affSColin Finck         return FALSE;
1019c2c66affSColin Finck     }
1020c2c66affSColin Finck 
1021c2c66affSColin Finck     /* Check if the DC has no surface (empty mem or info DC) */
1022c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1023c2c66affSColin Finck     {
1024c2c66affSColin Finck         /* Nothing to do, Windows returns TRUE! */
1025c2c66affSColin Finck         DC_UnlockDc(pdc);
1026c2c66affSColin Finck         return TRUE;
1027c2c66affSColin Finck     }
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     /* Update the fill brush, if necessary */
1030c2c66affSColin Finck     if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
1031c2c66affSColin Finck         DC_vUpdateFillBrush(pdc);
1032c2c66affSColin Finck 
1033c2c66affSColin Finck     /* Call the internal function */
1034c2c66affSColin Finck     bResult = IntPatBlt(pdc, x, y, cx, cy, dwRop, &pdc->eboFill);
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     /* Unlock the DC and return the result */
1037c2c66affSColin Finck     DC_UnlockDc(pdc);
1038c2c66affSColin Finck     return bResult;
1039c2c66affSColin Finck }
1040c2c66affSColin Finck 
1041c2c66affSColin Finck BOOL
1042c2c66affSColin Finck APIENTRY
NtGdiPolyPatBlt(HDC hDC,DWORD dwRop,IN PPOLYPATBLT pRects,IN DWORD cRects,IN DWORD Mode)1043c2c66affSColin Finck NtGdiPolyPatBlt(
1044c2c66affSColin Finck     HDC hDC,
1045c2c66affSColin Finck     DWORD dwRop,
1046c2c66affSColin Finck     IN PPOLYPATBLT pRects,
1047c2c66affSColin Finck     IN DWORD cRects,
1048c2c66affSColin Finck     IN DWORD Mode)
1049c2c66affSColin Finck {
1050c2c66affSColin Finck     PPATRECT rb = NULL;
1051c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
1052c2c66affSColin Finck     BOOL Ret;
1053c2c66affSColin Finck 
1054c2c66affSColin Finck     if (cRects > 0)
1055c2c66affSColin Finck     {
1056c2c66affSColin Finck         rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, GDITAG_PLGBLT_DATA);
1057c2c66affSColin Finck         if (!rb)
1058c2c66affSColin Finck         {
1059c2c66affSColin Finck             EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1060c2c66affSColin Finck             return FALSE;
1061c2c66affSColin Finck         }
1062c2c66affSColin Finck         _SEH2_TRY
1063c2c66affSColin Finck         {
1064c2c66affSColin Finck             ProbeForRead(pRects,
1065c2c66affSColin Finck                 cRects * sizeof(PATRECT),
1066c2c66affSColin Finck                 1);
1067c2c66affSColin Finck             RtlCopyMemory(rb,
1068c2c66affSColin Finck                 pRects,
1069c2c66affSColin Finck                 cRects * sizeof(PATRECT));
1070c2c66affSColin Finck         }
1071c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1072c2c66affSColin Finck         {
1073c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
1074c2c66affSColin Finck         }
1075c2c66affSColin Finck         _SEH2_END;
1076c2c66affSColin Finck 
1077c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1078c2c66affSColin Finck         {
1079c2c66affSColin Finck             ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
1080c2c66affSColin Finck             SetLastNtError(Status);
1081c2c66affSColin Finck             return FALSE;
1082c2c66affSColin Finck         }
1083c2c66affSColin Finck     }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck     Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
1086c2c66affSColin Finck 
1087c2c66affSColin Finck     if (cRects > 0)
1088c2c66affSColin Finck         ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
1089c2c66affSColin Finck 
1090c2c66affSColin Finck     return Ret;
1091c2c66affSColin Finck }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck static
1094c2c66affSColin Finck BOOL
1095c2c66affSColin Finck FASTCALL
REGION_LPTODP(_In_ PDC pdc,_Inout_ PREGION prgnDest,_In_ PREGION prgnSrc)1096c2c66affSColin Finck REGION_LPTODP(
1097c2c66affSColin Finck     _In_ PDC pdc,
1098c2c66affSColin Finck     _Inout_ PREGION prgnDest,
1099c2c66affSColin Finck     _In_ PREGION prgnSrc)
1100c2c66affSColin Finck {
1101c2c66affSColin Finck     if (IntGdiCombineRgn(prgnDest, prgnSrc, NULL, RGN_COPY) == ERROR)
1102c2c66affSColin Finck         return FALSE;
1103c2c66affSColin Finck 
1104c2c66affSColin Finck     return REGION_bXformRgn(prgnDest, DC_pmxWorldToDevice(pdc));
1105c2c66affSColin Finck }
1106c2c66affSColin Finck 
1107c2c66affSColin Finck BOOL
1108c2c66affSColin Finck APIENTRY
IntGdiBitBltRgn(_In_ PDC pdc,_In_ PREGION prgn,_In_opt_ BRUSHOBJ * pbo,_In_opt_ POINTL * pptlBrush,_In_ ROP4 rop4)1109c2c66affSColin Finck IntGdiBitBltRgn(
1110c2c66affSColin Finck     _In_ PDC pdc,
1111c2c66affSColin Finck     _In_ PREGION prgn,
1112c2c66affSColin Finck     _In_opt_ BRUSHOBJ *pbo,
1113c2c66affSColin Finck     _In_opt_ POINTL *pptlBrush,
1114c2c66affSColin Finck     _In_ ROP4 rop4)
1115c2c66affSColin Finck {
1116c2c66affSColin Finck     PREGION prgnClip;
1117c2c66affSColin Finck     XCLIPOBJ xcoClip;
1118c2c66affSColin Finck     BOOL bResult;
1119c2c66affSColin Finck     NT_ASSERT((pdc != NULL) && (prgn != NULL));
1120c2c66affSColin Finck 
1121c2c66affSColin Finck     /* Check if we have a surface */
1122c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1123c2c66affSColin Finck     {
1124c2c66affSColin Finck         return TRUE;
1125c2c66affSColin Finck     }
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     /* Create an empty clip region */
1128c2c66affSColin Finck     prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
1129c2c66affSColin Finck     if (prgnClip == NULL)
1130c2c66affSColin Finck     {
1131c2c66affSColin Finck         return FALSE;
1132c2c66affSColin Finck     }
1133c2c66affSColin Finck 
1134c2c66affSColin Finck     /* Transform given region into device coordinates */
1135c2c66affSColin Finck     if (!REGION_LPTODP(pdc, prgnClip, prgn))
1136c2c66affSColin Finck     {
1137c2c66affSColin Finck         REGION_Delete(prgnClip);
1138c2c66affSColin Finck         return FALSE;
1139c2c66affSColin Finck     }
1140c2c66affSColin Finck 
1141c2c66affSColin Finck     /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1142c2c66affSColin Finck     if (pdc->prgnRao)
1143c2c66affSColin Finck         IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND);
1144c2c66affSColin Finck     else
1145c2c66affSColin Finck         IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND);
1146c2c66affSColin Finck 
1147c2c66affSColin Finck     /* Now account for the DC-origin */
1148c2c66affSColin Finck     if (!REGION_bOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y))
1149c2c66affSColin Finck     {
1150c2c66affSColin Finck         REGION_Delete(prgnClip);
1151c2c66affSColin Finck         return FALSE;
1152c2c66affSColin Finck     }
1153c2c66affSColin Finck 
1154c2c66affSColin Finck     if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
1155c2c66affSColin Finck     {
1156c2c66affSColin Finck         RECTL rcrgn;
1157c2c66affSColin Finck         REGION_GetRgnBox(prgnClip, &rcrgn);
1158c2c66affSColin Finck         IntUpdateBoundsRect(pdc, &rcrgn);
1159c2c66affSColin Finck     }
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     /* Prepare the DC */
1162c2c66affSColin Finck     DC_vPrepareDCsForBlit(pdc, &prgnClip->rdh.rcBound, NULL, NULL);
1163c2c66affSColin Finck 
1164c2c66affSColin Finck     /* Initialize a clip object */
1165c2c66affSColin Finck     IntEngInitClipObj(&xcoClip);
1166c2c66affSColin Finck     IntEngUpdateClipRegion(&xcoClip,
1167c2c66affSColin Finck                            prgnClip->rdh.nCount,
1168c2c66affSColin Finck                            prgnClip->Buffer,
1169c2c66affSColin Finck                            &prgnClip->rdh.rcBound);
1170c2c66affSColin Finck 
1171c2c66affSColin Finck     /* Call the Eng or Drv function */
1172c2c66affSColin Finck     bResult = IntEngBitBlt(&pdc->dclevel.pSurface->SurfObj,
1173c2c66affSColin Finck                            NULL,
1174c2c66affSColin Finck                            NULL,
1175c2c66affSColin Finck                            (CLIPOBJ *)&xcoClip,
1176c2c66affSColin Finck                            NULL,
1177c2c66affSColin Finck                            &prgnClip->rdh.rcBound,
1178c2c66affSColin Finck                            NULL,
1179c2c66affSColin Finck                            NULL,
1180c2c66affSColin Finck                            pbo,
1181c2c66affSColin Finck                            pptlBrush,
1182c2c66affSColin Finck                            rop4);
1183c2c66affSColin Finck 
1184c2c66affSColin Finck     /* Cleanup */
1185c2c66affSColin Finck     DC_vFinishBlit(pdc, NULL);
1186c2c66affSColin Finck     REGION_Delete(prgnClip);
1187c2c66affSColin Finck     IntEngFreeClipResources(&xcoClip);
1188c2c66affSColin Finck 
1189c2c66affSColin Finck     /* Return the result */
1190c2c66affSColin Finck     return bResult;
1191c2c66affSColin Finck }
1192c2c66affSColin Finck 
1193c2c66affSColin Finck BOOL
IntGdiFillRgn(_In_ PDC pdc,_In_ PREGION prgn,_In_opt_ PBRUSH pbrFill)1194c2c66affSColin Finck IntGdiFillRgn(
1195c2c66affSColin Finck     _In_ PDC pdc,
1196c2c66affSColin Finck     _In_ PREGION prgn,
1197c2c66affSColin Finck     _In_opt_ PBRUSH pbrFill)
1198c2c66affSColin Finck {
1199c2c66affSColin Finck     PREGION prgnClip;
1200c2c66affSColin Finck     XCLIPOBJ xcoClip;
1201c2c66affSColin Finck     EBRUSHOBJ eboFill;
1202c2c66affSColin Finck     BRUSHOBJ *pbo;
1203c2c66affSColin Finck     BOOL bRet;
1204c2c66affSColin Finck     DWORD rop2Fg;
1205c2c66affSColin Finck     MIX mix;
1206c2c66affSColin Finck     NT_ASSERT((pdc != NULL) && (prgn != NULL));
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1209c2c66affSColin Finck     {
1210c2c66affSColin Finck         return TRUE;
1211c2c66affSColin Finck     }
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
1214c2c66affSColin Finck     if (prgnClip == NULL)
1215c2c66affSColin Finck     {
1216c2c66affSColin Finck         return FALSE;
1217c2c66affSColin Finck     }
1218c2c66affSColin Finck 
1219c2c66affSColin Finck     /* Transform region into device coordinates */
1220c2c66affSColin Finck     if (!REGION_LPTODP(pdc, prgnClip, prgn))
1221c2c66affSColin Finck     {
1222c2c66affSColin Finck         REGION_Delete(prgnClip);
1223c2c66affSColin Finck         return FALSE;
1224c2c66affSColin Finck     }
1225c2c66affSColin Finck 
1226c2c66affSColin Finck     /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1227c2c66affSColin Finck     if (pdc->prgnRao)
1228c2c66affSColin Finck         IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND);
1229c2c66affSColin Finck     else
1230c2c66affSColin Finck         IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND);
1231c2c66affSColin Finck 
1232c2c66affSColin Finck     /* Now account for the DC-origin */
1233c2c66affSColin Finck     if (!REGION_bOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y))
1234c2c66affSColin Finck     {
1235c2c66affSColin Finck         REGION_Delete(prgnClip);
1236c2c66affSColin Finck         return FALSE;
1237c2c66affSColin Finck     }
1238c2c66affSColin Finck 
1239c2c66affSColin Finck     if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
1240c2c66affSColin Finck     {
1241c2c66affSColin Finck         RECTL rcrgn;
1242c2c66affSColin Finck         REGION_GetRgnBox(prgnClip, &rcrgn);
1243c2c66affSColin Finck         IntUpdateBoundsRect(pdc, &rcrgn);
1244c2c66affSColin Finck     }
1245c2c66affSColin Finck 
1246c2c66affSColin Finck     IntEngInitClipObj(&xcoClip);
1247c2c66affSColin Finck     IntEngUpdateClipRegion(&xcoClip,
1248c2c66affSColin Finck                            prgnClip->rdh.nCount,
1249c2c66affSColin Finck                            prgnClip->Buffer,
1250c2c66affSColin Finck                            &prgnClip->rdh.rcBound );
1251c2c66affSColin Finck 
1252c2c66affSColin Finck     /* Get the FG rop and create a MIX based on the BK mode */
1253c2c66affSColin Finck     rop2Fg = FIXUP_ROP2(pdc->pdcattr->jROP2);
1254c2c66affSColin Finck     mix = rop2Fg | (pdc->pdcattr->jBkMode == OPAQUE ? rop2Fg : R2_NOP) << 8;
1255c2c66affSColin Finck 
1256c2c66affSColin Finck     /* Prepare DC for blit */
1257c2c66affSColin Finck     DC_vPrepareDCsForBlit(pdc, &prgnClip->rdh.rcBound, NULL, NULL);
1258c2c66affSColin Finck 
1259c2c66affSColin Finck     /* Check if we have a fill brush */
1260c2c66affSColin Finck     if (pbrFill != NULL)
1261c2c66affSColin Finck     {
1262c2c66affSColin Finck         /* Initialize the brush object */
1263c2c66affSColin Finck         /// \todo Check parameters
1264c2c66affSColin Finck         EBRUSHOBJ_vInit(&eboFill, pbrFill, pdc->dclevel.pSurface, 0x00FFFFFF, 0, NULL);
1265c2c66affSColin Finck         pbo = &eboFill.BrushObject;
1266c2c66affSColin Finck     }
1267c2c66affSColin Finck     else
1268c2c66affSColin Finck     {
1269c2c66affSColin Finck         /* Update the fill brush if needed */
1270c2c66affSColin Finck         if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
1271c2c66affSColin Finck             DC_vUpdateFillBrush(pdc);
1272c2c66affSColin Finck 
1273c2c66affSColin Finck         /* Use the DC brush object */
1274c2c66affSColin Finck         pbo = &pdc->eboFill.BrushObject;
1275c2c66affSColin Finck     }
1276c2c66affSColin Finck 
1277c2c66affSColin Finck     /* Call the internal function */
1278c2c66affSColin Finck     bRet = IntEngPaint(&pdc->dclevel.pSurface->SurfObj,
1279c2c66affSColin Finck                        (CLIPOBJ *)&xcoClip,
1280c2c66affSColin Finck                        pbo,
1281c2c66affSColin Finck                        &pdc->pdcattr->ptlBrushOrigin,
1282c2c66affSColin Finck                        mix);
1283c2c66affSColin Finck 
1284c2c66affSColin Finck     DC_vFinishBlit(pdc, NULL);
1285c2c66affSColin Finck     REGION_Delete(prgnClip);
1286c2c66affSColin Finck     IntEngFreeClipResources(&xcoClip);
1287c2c66affSColin Finck 
1288c2c66affSColin Finck     // Fill the region
1289c2c66affSColin Finck     return bRet;
1290c2c66affSColin Finck }
1291c2c66affSColin Finck 
1292c2c66affSColin Finck BOOL
1293c2c66affSColin Finck FASTCALL
IntGdiPaintRgn(_In_ PDC pdc,_In_ PREGION prgn)1294c2c66affSColin Finck IntGdiPaintRgn(
1295c2c66affSColin Finck     _In_ PDC pdc,
1296c2c66affSColin Finck     _In_ PREGION prgn)
1297c2c66affSColin Finck {
1298c2c66affSColin Finck     return IntGdiFillRgn(pdc, prgn, NULL);
1299c2c66affSColin Finck }
1300c2c66affSColin Finck 
1301c2c66affSColin Finck BOOL
1302c2c66affSColin Finck APIENTRY
NtGdiFillRgn(_In_ HDC hdc,_In_ HRGN hrgn,_In_ HBRUSH hbrush)1303c2c66affSColin Finck NtGdiFillRgn(
1304c2c66affSColin Finck     _In_ HDC hdc,
1305c2c66affSColin Finck     _In_ HRGN hrgn,
1306c2c66affSColin Finck     _In_ HBRUSH hbrush)
1307c2c66affSColin Finck {
1308c2c66affSColin Finck     PDC pdc;
1309c2c66affSColin Finck     PREGION prgn;
1310c2c66affSColin Finck     PBRUSH pbrFill;
1311c2c66affSColin Finck     BOOL bResult;
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     /* Lock the DC */
1314c2c66affSColin Finck     pdc = DC_LockDc(hdc);
1315c2c66affSColin Finck     if (pdc == NULL)
1316c2c66affSColin Finck     {
1317c2c66affSColin Finck         ERR("Failed to lock hdc %p\n", hdc);
1318c2c66affSColin Finck         return FALSE;
1319c2c66affSColin Finck     }
1320c2c66affSColin Finck 
1321c2c66affSColin Finck     /* Check if the DC has no surface (empty mem or info DC) */
1322c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1323c2c66affSColin Finck     {
1324c2c66affSColin Finck         DC_UnlockDc(pdc);
1325c2c66affSColin Finck         return TRUE;
1326c2c66affSColin Finck     }
1327c2c66affSColin Finck 
1328c2c66affSColin Finck     /* Lock the region */
1329c2c66affSColin Finck     prgn = REGION_LockRgn(hrgn);
1330c2c66affSColin Finck     if (prgn == NULL)
1331c2c66affSColin Finck     {
1332c2c66affSColin Finck         ERR("Failed to lock hrgn %p\n", hrgn);
1333c2c66affSColin Finck         DC_UnlockDc(pdc);
1334c2c66affSColin Finck         return FALSE;
1335c2c66affSColin Finck     }
1336c2c66affSColin Finck 
1337c2c66affSColin Finck     /* Lock the brush */
1338c2c66affSColin Finck     pbrFill = BRUSH_ShareLockBrush(hbrush);
1339c2c66affSColin Finck     if (pbrFill == NULL)
1340c2c66affSColin Finck     {
1341c2c66affSColin Finck         ERR("Failed to lock hbrush %p\n", hbrush);
1342c2c66affSColin Finck         REGION_UnlockRgn(prgn);
1343c2c66affSColin Finck         DC_UnlockDc(pdc);
1344c2c66affSColin Finck         return FALSE;
1345c2c66affSColin Finck     }
1346c2c66affSColin Finck 
1347c2c66affSColin Finck     /* Call the internal function */
1348c2c66affSColin Finck     bResult = IntGdiFillRgn(pdc, prgn, pbrFill);
1349c2c66affSColin Finck 
1350c2c66affSColin Finck     /* Cleanup locks */
1351c2c66affSColin Finck     BRUSH_ShareUnlockBrush(pbrFill);
1352c2c66affSColin Finck     REGION_UnlockRgn(prgn);
1353c2c66affSColin Finck     DC_UnlockDc(pdc);
1354c2c66affSColin Finck 
1355c2c66affSColin Finck     return bResult;
1356c2c66affSColin Finck }
1357c2c66affSColin Finck 
1358c2c66affSColin Finck BOOL
1359c2c66affSColin Finck APIENTRY
NtGdiFrameRgn(_In_ HDC hdc,_In_ HRGN hrgn,_In_ HBRUSH hbrush,_In_ INT xWidth,_In_ INT yHeight)1360c2c66affSColin Finck NtGdiFrameRgn(
1361c2c66affSColin Finck     _In_ HDC hdc,
1362c2c66affSColin Finck     _In_ HRGN hrgn,
1363c2c66affSColin Finck     _In_ HBRUSH hbrush,
1364c2c66affSColin Finck     _In_ INT xWidth,
1365c2c66affSColin Finck     _In_ INT yHeight)
1366c2c66affSColin Finck {
1367c2c66affSColin Finck     HRGN hrgnFrame;
1368c2c66affSColin Finck     BOOL bResult;
1369c2c66affSColin Finck 
1370c2c66affSColin Finck     hrgnFrame = GreCreateFrameRgn(hrgn, xWidth, yHeight);
1371c2c66affSColin Finck     if (hrgnFrame == NULL)
1372c2c66affSColin Finck     {
1373c2c66affSColin Finck         return FALSE;
1374c2c66affSColin Finck     }
1375c2c66affSColin Finck 
1376c2c66affSColin Finck     bResult = NtGdiFillRgn(hdc, hrgnFrame, hbrush);
1377c2c66affSColin Finck 
1378c2c66affSColin Finck     GreDeleteObject(hrgnFrame);
1379c2c66affSColin Finck     return bResult;
1380c2c66affSColin Finck }
1381c2c66affSColin Finck 
1382c2c66affSColin Finck BOOL
1383c2c66affSColin Finck APIENTRY
NtGdiInvertRgn(_In_ HDC hdc,_In_ HRGN hrgn)1384c2c66affSColin Finck NtGdiInvertRgn(
1385c2c66affSColin Finck     _In_ HDC hdc,
1386c2c66affSColin Finck     _In_ HRGN hrgn)
1387c2c66affSColin Finck {
1388c2c66affSColin Finck     BOOL bResult;
1389c2c66affSColin Finck     PDC pdc;
1390c2c66affSColin Finck     PREGION prgn;
1391c2c66affSColin Finck 
1392c2c66affSColin Finck     /* Lock the DC */
1393c2c66affSColin Finck     pdc = DC_LockDc(hdc);
1394c2c66affSColin Finck     if (pdc == NULL)
1395c2c66affSColin Finck     {
1396c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1397c2c66affSColin Finck         return FALSE;
1398c2c66affSColin Finck     }
1399c2c66affSColin Finck 
1400c2c66affSColin Finck     /* Check if the DC has no surface (empty mem or info DC) */
1401c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1402c2c66affSColin Finck     {
1403c2c66affSColin Finck         /* Nothing to do, Windows returns TRUE! */
1404c2c66affSColin Finck         DC_UnlockDc(pdc);
1405c2c66affSColin Finck         return TRUE;
1406c2c66affSColin Finck     }
1407c2c66affSColin Finck 
1408c2c66affSColin Finck     /* Lock the region */
1409c2c66affSColin Finck     prgn = REGION_LockRgn(hrgn);
1410c2c66affSColin Finck     if (prgn == NULL)
1411c2c66affSColin Finck     {
1412c2c66affSColin Finck         DC_UnlockDc(pdc);
1413c2c66affSColin Finck         return FALSE;
1414c2c66affSColin Finck     }
1415c2c66affSColin Finck 
1416c2c66affSColin Finck     /* Call the internal function */
1417c2c66affSColin Finck     bResult = IntGdiBitBltRgn(pdc,
1418c2c66affSColin Finck                               prgn,
1419c2c66affSColin Finck                               NULL, // pbo
1420c2c66affSColin Finck                               NULL, // pptlBrush,
1421c2c66affSColin Finck                               ROP4_DSTINVERT);
1422c2c66affSColin Finck 
1423c2c66affSColin Finck     /* Unlock the region and DC and return the result */
1424c2c66affSColin Finck     REGION_UnlockRgn(prgn);
1425c2c66affSColin Finck     DC_UnlockDc(pdc);
1426c2c66affSColin Finck     return bResult;
1427c2c66affSColin Finck }
1428c2c66affSColin Finck 
1429c2c66affSColin Finck COLORREF
1430c2c66affSColin Finck APIENTRY
NtGdiSetPixel(_In_ HDC hdc,_In_ INT x,_In_ INT y,_In_ COLORREF crColor)1431c2c66affSColin Finck NtGdiSetPixel(
1432c2c66affSColin Finck     _In_ HDC hdc,
1433c2c66affSColin Finck     _In_ INT x,
1434c2c66affSColin Finck     _In_ INT y,
1435c2c66affSColin Finck     _In_ COLORREF crColor)
1436c2c66affSColin Finck {
1437c2c66affSColin Finck     PDC pdc;
1438c2c66affSColin Finck     ULONG iOldColor, iSolidColor;
1439c2c66affSColin Finck     BOOL bResult;
1440c2c66affSColin Finck     PEBRUSHOBJ pebo;
1441c2c66affSColin Finck     ULONG ulDirty;
1442c2c66affSColin Finck     EXLATEOBJ exlo;
1443c2c66affSColin Finck 
1444c2c66affSColin Finck     /* Lock the DC */
1445c2c66affSColin Finck     pdc = DC_LockDc(hdc);
1446c2c66affSColin Finck     if (!pdc)
1447c2c66affSColin Finck     {
1448c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1449c2c66affSColin Finck         return -1;
1450c2c66affSColin Finck     }
1451c2c66affSColin Finck 
1452c2c66affSColin Finck     /* Check if the DC has no surface (empty mem or info DC) */
1453c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1454c2c66affSColin Finck     {
1455c2c66affSColin Finck         /* Fail! */
1456c2c66affSColin Finck         DC_UnlockDc(pdc);
1457c2c66affSColin Finck         return -1;
1458c2c66affSColin Finck     }
1459c2c66affSColin Finck 
1460c2c66affSColin Finck     if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
1461c2c66affSColin Finck     {
1462c2c66affSColin Finck        RECTL rcDst;
1463c2c66affSColin Finck 
1464c2c66affSColin Finck        RECTL_vSetRect(&rcDst, x, y, x+1, y+1);
1465c2c66affSColin Finck 
1466c2c66affSColin Finck        IntLPtoDP(pdc, (LPPOINT)&rcDst, 2);
1467c2c66affSColin Finck 
1468c2c66affSColin Finck        rcDst.left   += pdc->ptlDCOrig.x;
1469c2c66affSColin Finck        rcDst.top    += pdc->ptlDCOrig.y;
1470c2c66affSColin Finck        rcDst.right  += pdc->ptlDCOrig.x;
1471c2c66affSColin Finck        rcDst.bottom += pdc->ptlDCOrig.y;
1472c2c66affSColin Finck 
1473c2c66affSColin Finck        IntUpdateBoundsRect(pdc, &rcDst);
1474c2c66affSColin Finck     }
1475c2c66affSColin Finck 
1476c2c66affSColin Finck     /* Translate the color to the target format */
1477c2c66affSColin Finck     iSolidColor = TranslateCOLORREF(pdc, crColor);
1478c2c66affSColin Finck 
1479c2c66affSColin Finck     /* Use the DC's text brush, which is always a solid brush */
1480c2c66affSColin Finck     pebo = &pdc->eboText;
1481c2c66affSColin Finck 
1482c2c66affSColin Finck     /* Save the old solid color and set the one for the pixel */
1483c2c66affSColin Finck     iOldColor = EBRUSHOBJ_iSetSolidColor(pebo, iSolidColor);
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     /* Save dirty flags and reset dirty text brush flag */
1486c2c66affSColin Finck     ulDirty = pdc->pdcattr->ulDirty_;
1487c2c66affSColin Finck     pdc->pdcattr->ulDirty_ &= ~DIRTY_TEXT;
1488c2c66affSColin Finck 
1489c2c66affSColin Finck     /* Call the internal function */
1490c2c66affSColin Finck     bResult = IntPatBlt(pdc, x, y, 1, 1, PATCOPY, pebo);
1491c2c66affSColin Finck 
1492c2c66affSColin Finck     /* Restore old text brush color and dirty flags */
1493c2c66affSColin Finck     EBRUSHOBJ_iSetSolidColor(pebo, iOldColor);
1494c2c66affSColin Finck     pdc->pdcattr->ulDirty_ = ulDirty;
1495c2c66affSColin Finck 
1496c2c66affSColin Finck     /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked!
1497c2c66affSColin Finck     /* Initialize an XLATEOBJ from the target surface to RGB */
1498c2c66affSColin Finck     EXLATEOBJ_vInitialize(&exlo,
1499c2c66affSColin Finck                           pdc->dclevel.pSurface->ppal,
1500c2c66affSColin Finck                           &gpalRGB,
1501c2c66affSColin Finck                           0,
1502c2c66affSColin Finck                           pdc->pdcattr->crBackgroundClr,
1503c2c66affSColin Finck                           pdc->pdcattr->crForegroundClr);
1504c2c66affSColin Finck 
1505c2c66affSColin Finck     /* Translate the color back to RGB */
1506c2c66affSColin Finck     crColor = XLATEOBJ_iXlate(&exlo.xlo, iSolidColor);
1507c2c66affSColin Finck 
1508c2c66affSColin Finck     /* Cleanup and return the target format color */
1509c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
1510c2c66affSColin Finck 
1511c2c66affSColin Finck     /* Unlock the DC */
1512c2c66affSColin Finck     DC_UnlockDc(pdc);
1513c2c66affSColin Finck 
1514c2c66affSColin Finck     /* Return the new RGB color or -1 on failure */
1515c2c66affSColin Finck     return bResult ? crColor : -1;
1516c2c66affSColin Finck }
1517c2c66affSColin Finck 
1518c2c66affSColin Finck COLORREF
1519c2c66affSColin Finck APIENTRY
NtGdiGetPixel(_In_ HDC hdc,_In_ INT x,_In_ INT y)1520c2c66affSColin Finck NtGdiGetPixel(
1521c2c66affSColin Finck     _In_ HDC hdc,
1522c2c66affSColin Finck     _In_ INT x,
1523c2c66affSColin Finck     _In_ INT y)
1524c2c66affSColin Finck {
1525c2c66affSColin Finck     PDC pdc;
1526c2c66affSColin Finck     ULONG ulRGBColor = CLR_INVALID;
1527c2c66affSColin Finck     POINTL ptlSrc;
1528c2c66affSColin Finck     RECT rcDest;
1529c2c66affSColin Finck     PSURFACE psurfSrc, psurfDest;
1530c2c66affSColin Finck 
1531c2c66affSColin Finck     /* Lock the DC */
1532c2c66affSColin Finck     pdc = DC_LockDc(hdc);
1533c2c66affSColin Finck     if (!pdc)
1534c2c66affSColin Finck     {
1535c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1536c2c66affSColin Finck         return CLR_INVALID;
1537c2c66affSColin Finck     }
1538c2c66affSColin Finck 
1539c2c66affSColin Finck     /* Check if the DC has no surface (empty mem or info DC) */
1540c2c66affSColin Finck     if (pdc->dclevel.pSurface == NULL)
1541c2c66affSColin Finck     {
1542c2c66affSColin Finck         /* Fail! */
1543c2c66affSColin Finck         goto leave;
1544c2c66affSColin Finck     }
1545c2c66affSColin Finck 
1546c2c66affSColin Finck     /* Get the logical coordinates */
1547c2c66affSColin Finck     ptlSrc.x = x;
1548c2c66affSColin Finck     ptlSrc.y = y;
1549c2c66affSColin Finck 
1550c2c66affSColin Finck     /* Translate coordinates to device coordinates */
1551c2c66affSColin Finck     IntLPtoDP(pdc, &ptlSrc, 1);
1552c2c66affSColin Finck     ptlSrc.x += pdc->ptlDCOrig.x;
1553c2c66affSColin Finck     ptlSrc.y += pdc->ptlDCOrig.y;
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     rcDest.left = x;
1556c2c66affSColin Finck     rcDest.top = y;
1557c2c66affSColin Finck     rcDest.right = x + 1;
1558c2c66affSColin Finck     rcDest.bottom = y + 1;
1559c2c66affSColin Finck 
1560c2c66affSColin Finck     /* Prepare DC for blit */
1561c2c66affSColin Finck     DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
1562c2c66affSColin Finck 
1563c2c66affSColin Finck     /* Check if the pixel is outside the surface */
1564c2c66affSColin Finck     psurfSrc = pdc->dclevel.pSurface;
1565c2c66affSColin Finck     if ((ptlSrc.x >= psurfSrc->SurfObj.sizlBitmap.cx) ||
1566c2c66affSColin Finck         (ptlSrc.y >= psurfSrc->SurfObj.sizlBitmap.cy) ||
1567c2c66affSColin Finck         (ptlSrc.x < 0) ||
1568c2c66affSColin Finck         (ptlSrc.y < 0))
1569c2c66affSColin Finck     {
1570c2c66affSColin Finck         /* Fail! */
1571c2c66affSColin Finck         goto leave;
1572c2c66affSColin Finck     }
1573c2c66affSColin Finck 
1574c2c66affSColin Finck     /* Allocate a surface */
1575c2c66affSColin Finck     psurfDest = SURFACE_AllocSurface(STYPE_BITMAP,
1576c2c66affSColin Finck                                      1,
1577c2c66affSColin Finck                                      1,
1578c2c66affSColin Finck                                      BMF_32BPP,
1579c2c66affSColin Finck                                      0,
1580c2c66affSColin Finck                                      0,
1581c2c66affSColin Finck                                      0,
1582c2c66affSColin Finck                                      &ulRGBColor);
1583c2c66affSColin Finck     if (psurfDest)
1584c2c66affSColin Finck     {
1585c2c66affSColin Finck         RECTL rclDest = {0, 0, 1, 1};
1586c2c66affSColin Finck         EXLATEOBJ exlo;
1587c2c66affSColin Finck 
1588c2c66affSColin Finck         /* Translate from the source palette to RGB color */
1589c2c66affSColin Finck         EXLATEOBJ_vInitialize(&exlo,
1590c2c66affSColin Finck                               psurfSrc->ppal,
1591c2c66affSColin Finck                               &gpalRGB,
1592c2c66affSColin Finck                               0,
1593c2c66affSColin Finck                               RGB(0xff,0xff,0xff),
1594c2c66affSColin Finck                               RGB(0,0,0));
1595c2c66affSColin Finck 
1596c2c66affSColin Finck         /* Call the copy bits function */
1597c2c66affSColin Finck         EngCopyBits(&psurfDest->SurfObj,
1598c2c66affSColin Finck                     &psurfSrc->SurfObj,
1599c2c66affSColin Finck                     NULL,
1600c2c66affSColin Finck                     &exlo.xlo,
1601c2c66affSColin Finck                     &rclDest,
1602c2c66affSColin Finck                     &ptlSrc);
1603c2c66affSColin Finck 
1604c2c66affSColin Finck         /* Cleanup the XLATEOBJ */
1605c2c66affSColin Finck         EXLATEOBJ_vCleanup(&exlo);
1606c2c66affSColin Finck 
1607c2c66affSColin Finck         /* Delete the surface */
1608c2c66affSColin Finck         GDIOBJ_vDeleteObject(&psurfDest->BaseObject);
16092a16fc5eSKatayama Hirofumi MZ 
16102a16fc5eSKatayama Hirofumi MZ         /* The top byte is zero */
16112a16fc5eSKatayama Hirofumi MZ         ulRGBColor &= 0x00FFFFFF;
1612c2c66affSColin Finck     }
1613c2c66affSColin Finck 
1614c2c66affSColin Finck leave:
1615c2c66affSColin Finck 
1616c2c66affSColin Finck     /* Unlock the DC */
1617c2c66affSColin Finck     DC_vFinishBlit(pdc, NULL);
1618c2c66affSColin Finck     DC_UnlockDc(pdc);
1619c2c66affSColin Finck 
1620c2c66affSColin Finck     /* Return the new RGB color or -1 on failure */
1621c2c66affSColin Finck     return ulRGBColor;
1622c2c66affSColin Finck }
1623c2c66affSColin Finck 
1624