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