TEB.StackLimit should not include the guard page.
[wine/multimedia.git] / dlls / gdi / bitblt.c
blobd15b39a64ca86d5f3295dd5d03358542cec4f9cb
1 /*
2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "gdi.h"
22 #include "gdi_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
28 /***********************************************************************
29 * PatBlt (GDI32.@)
31 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
32 INT width, INT height, DWORD rop)
34 DC * dc = DC_GetDCUpdate( hdc );
35 BOOL bRet = FALSE;
37 if (!dc) return FALSE;
39 if (dc->funcs->pPatBlt)
41 TRACE("%p %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
42 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
44 GDI_ReleaseObj( hdc );
45 return bRet;
49 /***********************************************************************
50 * BitBlt (GDI32.@)
52 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
53 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
55 BOOL ret = FALSE;
56 DC *dcDst, *dcSrc;
58 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
59 /* FIXME: there is a race condition here */
60 if ((dcDst = DC_GetDCUpdate( hdcDst )))
62 dcSrc = DC_GetDCPtr( hdcSrc );
63 TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06lx\n",
64 hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, rop);
65 if (dcDst->funcs->pBitBlt)
66 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
67 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
68 if (dcSrc) GDI_ReleaseObj( hdcSrc );
69 GDI_ReleaseObj( hdcDst );
71 return ret;
75 /***********************************************************************
76 * StretchBlt (GDI32.@)
78 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
79 INT widthDst, INT heightDst,
80 HDC hdcSrc, INT xSrc, INT ySrc,
81 INT widthSrc, INT heightSrc,
82 DWORD rop )
84 BOOL ret = FALSE;
85 DC *dcDst, *dcSrc;
87 if ((dcDst = DC_GetDCUpdate( hdcDst )) && dcDst->funcs->pStretchBlt)
89 GDI_ReleaseObj( hdcDst );
90 /* FIXME: there is a race condition here */
91 if ((dcSrc = DC_GetDCUpdate( hdcSrc )))
93 dcDst = DC_GetDCPtr( hdcDst );
95 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06lx\n",
96 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
97 hdcDst, xDst, yDst, widthDst, heightDst, rop );
99 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
100 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
101 rop );
102 GDI_ReleaseObj( hdcDst );
103 GDI_ReleaseObj( hdcSrc );
106 else if(dcDst && dcDst->funcs->pStretchDIBits)
108 BITMAP bm;
109 BITMAPINFOHEADER info_hdr;
110 HBITMAP hbm;
111 LPVOID bits;
112 INT lines;
114 GDI_ReleaseObj( hdcDst );
116 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
118 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
120 info_hdr.biSize = sizeof(info_hdr);
121 info_hdr.biWidth = bm.bmWidth;
122 info_hdr.biHeight = bm.bmHeight;
123 info_hdr.biPlanes = 1;
124 info_hdr.biBitCount = 32;
125 info_hdr.biCompression = BI_RGB;
126 info_hdr.biSizeImage = 0;
127 info_hdr.biXPelsPerMeter = 0;
128 info_hdr.biYPelsPerMeter = 0;
129 info_hdr.biClrUsed = 0;
130 info_hdr.biClrImportant = 0;
132 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
133 return FALSE;
135 /* Select out the src bitmap before calling GetDIBits */
136 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
137 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
138 SelectObject(hdcSrc, hbm);
140 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc,
141 bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
143 HeapFree(GetProcessHeap(), 0, bits);
144 return (lines == bm.bmHeight);
146 else if(dcDst)
147 GDI_ReleaseObj( hdcDst );
149 return ret;
152 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
153 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
155 /***********************************************************************
156 * MaskBlt [GDI32.@]
158 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
159 INT nWidth, INT nHeight, HDC hdcSrc,
160 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
161 INT xMask, INT yMask, DWORD dwRop)
163 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
164 HDC hDC1, hDC2;
165 HBRUSH hbrMask, hbrDst, hbrTmp;
167 static const DWORD ROP3Table[256] =
169 0x00000042, 0x00010289,
170 0x00020C89, 0x000300AA,
171 0x00040C88, 0x000500A9,
172 0x00060865, 0x000702C5,
173 0x00080F08, 0x00090245,
174 0x000A0329, 0x000B0B2A,
175 0x000C0324, 0x000D0B25,
176 0x000E08A5, 0x000F0001,
177 0x00100C85, 0x001100A6,
178 0x00120868, 0x001302C8,
179 0x00140869, 0x001502C9,
180 0x00165CCA, 0x00171D54,
181 0x00180D59, 0x00191CC8,
182 0x001A06C5, 0x001B0768,
183 0x001C06CA, 0x001D0766,
184 0x001E01A5, 0x001F0385,
185 0x00200F09, 0x00210248,
186 0x00220326, 0x00230B24,
187 0x00240D55, 0x00251CC5,
188 0x002606C8, 0x00271868,
189 0x00280369, 0x002916CA,
190 0x002A0CC9, 0x002B1D58,
191 0x002C0784, 0x002D060A,
192 0x002E064A, 0x002F0E2A,
193 0x0030032A, 0x00310B28,
194 0x00320688, 0x00330008,
195 0x003406C4, 0x00351864,
196 0x003601A8, 0x00370388,
197 0x0038078A, 0x00390604,
198 0x003A0644, 0x003B0E24,
199 0x003C004A, 0x003D18A4,
200 0x003E1B24, 0x003F00EA,
201 0x00400F0A, 0x00410249,
202 0x00420D5D, 0x00431CC4,
203 0x00440328, 0x00450B29,
204 0x004606C6, 0x0047076A,
205 0x00480368, 0x004916C5,
206 0x004A0789, 0x004B0605,
207 0x004C0CC8, 0x004D1954,
208 0x004E0645, 0x004F0E25,
209 0x00500325, 0x00510B26,
210 0x005206C9, 0x00530764,
211 0x005408A9, 0x00550009,
212 0x005601A9, 0x00570389,
213 0x00580785, 0x00590609,
214 0x005A0049, 0x005B18A9,
215 0x005C0649, 0x005D0E29,
216 0x005E1B29, 0x005F00E9,
217 0x00600365, 0x006116C6,
218 0x00620786, 0x00630608,
219 0x00640788, 0x00650606,
220 0x00660046, 0x006718A8,
221 0x006858A6, 0x00690145,
222 0x006A01E9, 0x006B178A,
223 0x006C01E8, 0x006D1785,
224 0x006E1E28, 0x006F0C65,
225 0x00700CC5, 0x00711D5C,
226 0x00720648, 0x00730E28,
227 0x00740646, 0x00750E26,
228 0x00761B28, 0x007700E6,
229 0x007801E5, 0x00791786,
230 0x007A1E29, 0x007B0C68,
231 0x007C1E24, 0x007D0C69,
232 0x007E0955, 0x007F03C9,
233 0x008003E9, 0x00810975,
234 0x00820C49, 0x00831E04,
235 0x00840C48, 0x00851E05,
236 0x008617A6, 0x008701C5,
237 0x008800C6, 0x00891B08,
238 0x008A0E06, 0x008B0666,
239 0x008C0E08, 0x008D0668,
240 0x008E1D7C, 0x008F0CE5,
241 0x00900C45, 0x00911E08,
242 0x009217A9, 0x009301C4,
243 0x009417AA, 0x009501C9,
244 0x00960169, 0x0097588A,
245 0x00981888, 0x00990066,
246 0x009A0709, 0x009B07A8,
247 0x009C0704, 0x009D07A6,
248 0x009E16E6, 0x009F0345,
249 0x00A000C9, 0x00A11B05,
250 0x00A20E09, 0x00A30669,
251 0x00A41885, 0x00A50065,
252 0x00A60706, 0x00A707A5,
253 0x00A803A9, 0x00A90189,
254 0x00AA0029, 0x00AB0889,
255 0x00AC0744, 0x00AD06E9,
256 0x00AE0B06, 0x00AF0229,
257 0x00B00E05, 0x00B10665,
258 0x00B21974, 0x00B30CE8,
259 0x00B4070A, 0x00B507A9,
260 0x00B616E9, 0x00B70348,
261 0x00B8074A, 0x00B906E6,
262 0x00BA0B09, 0x00BB0226,
263 0x00BC1CE4, 0x00BD0D7D,
264 0x00BE0269, 0x00BF08C9,
265 0x00C000CA, 0x00C11B04,
266 0x00C21884, 0x00C3006A,
267 0x00C40E04, 0x00C50664,
268 0x00C60708, 0x00C707AA,
269 0x00C803A8, 0x00C90184,
270 0x00CA0749, 0x00CB06E4,
271 0x00CC0020, 0x00CD0888,
272 0x00CE0B08, 0x00CF0224,
273 0x00D00E0A, 0x00D1066A,
274 0x00D20705, 0x00D307A4,
275 0x00D41D78, 0x00D50CE9,
276 0x00D616EA, 0x00D70349,
277 0x00D80745, 0x00D906E8,
278 0x00DA1CE9, 0x00DB0D75,
279 0x00DC0B04, 0x00DD0228,
280 0x00DE0268, 0x00DF08C8,
281 0x00E003A5, 0x00E10185,
282 0x00E20746, 0x00E306EA,
283 0x00E40748, 0x00E506E5,
284 0x00E61CE8, 0x00E70D79,
285 0x00E81D74, 0x00E95CE6,
286 0x00EA02E9, 0x00EB0849,
287 0x00EC02E8, 0x00ED0848,
288 0x00EE0086, 0x00EF0A08,
289 0x00F00021, 0x00F10885,
290 0x00F20B05, 0x00F3022A,
291 0x00F40B0A, 0x00F50225,
292 0x00F60265, 0x00F708C5,
293 0x00F802E5, 0x00F90845,
294 0x00FA0089, 0x00FB0A09,
295 0x00FC008A, 0x00FD0A0A,
296 0x00FE02A9, 0x00FF0062,
299 if (!hbmMask)
300 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
302 hbrMask = CreatePatternBrush(hbmMask);
303 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
305 /* make bitmap */
306 hDC1 = CreateCompatibleDC(hdcDest);
307 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
308 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
310 /* draw using bkgnd rop */
311 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
312 hbrTmp = SelectObject(hDC1, hbrDst);
313 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
314 SelectObject(hDC1, hbrTmp);
316 /* make bitmap */
317 hDC2 = CreateCompatibleDC(hdcDest);
318 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
319 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
321 /* draw using foregnd rop */
322 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
323 hbrTmp = SelectObject(hDC2, hbrDst);
324 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
326 /* combine both using the mask as a pattern brush */
327 SelectObject(hDC2, hbrMask);
328 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
329 SelectObject(hDC2, hbrTmp);
331 /* blit to dst */
332 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
334 /* restore all objects */
335 SelectObject(hdcDest, hbrDst);
336 SelectObject(hDC1, hOldBitmap1);
337 SelectObject(hDC2, hOldBitmap2);
339 /* delete all temp objects */
340 DeleteObject(hBitmap1);
341 DeleteObject(hBitmap2);
342 DeleteObject(hbrMask);
344 DeleteDC(hDC1);
345 DeleteDC(hDC2);
347 return TRUE;
350 /******************************************************************************
351 * GdiTransparentBlt [GDI32.@]
353 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
354 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
355 UINT crTransparent )
357 BOOL ret = FALSE;
358 HDC hdcWork;
359 HBITMAP bmpWork;
360 HGDIOBJ oldWork;
361 HDC hdcMask = NULL;
362 HBITMAP bmpMask = NULL;
363 HBITMAP oldMask = NULL;
364 COLORREF oldBackground;
365 COLORREF oldForeground;
366 int oldStretchMode;
368 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
369 TRACE("Cannot mirror\n");
370 return FALSE;
373 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
374 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
376 /* Stretch bitmap */
377 oldStretchMode = GetStretchBltMode(hdcSrc);
378 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
379 SetStretchBltMode(hdcSrc, COLORONCOLOR);
380 hdcWork = CreateCompatibleDC(hdcDest);
381 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
382 oldWork = SelectObject(hdcWork, bmpWork);
383 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
384 TRACE("Failed to stretch\n");
385 goto error;
387 SetBkColor(hdcWork, crTransparent);
389 /* Create mask */
390 hdcMask = CreateCompatibleDC(hdcDest);
391 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
392 oldMask = SelectObject(hdcMask, bmpMask);
393 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
394 TRACE("Failed to create mask\n");
395 goto error;
398 /* Replace transparent color with black */
399 SetBkColor(hdcWork, RGB(0,0,0));
400 SetTextColor(hdcWork, RGB(255,255,255));
401 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
402 TRACE("Failed to mask out background\n");
403 goto error;
406 /* Replace non-transparent area on destination with black */
407 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
408 TRACE("Failed to clear destination area\n");
409 goto error;
412 /* Draw the image */
413 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
414 TRACE("Failed to paint image\n");
415 goto error;
418 ret = TRUE;
419 error:
420 SetStretchBltMode(hdcSrc, oldStretchMode);
421 SetBkColor(hdcDest, oldBackground);
422 SetTextColor(hdcDest, oldForeground);
423 if(hdcWork) {
424 SelectObject(hdcWork, oldWork);
425 DeleteDC(hdcWork);
427 if(bmpWork) DeleteObject(bmpWork);
428 if(hdcMask) {
429 SelectObject(hdcMask, oldMask);
430 DeleteDC(hdcMask);
432 if(bmpMask) DeleteObject(bmpMask);
433 return ret;
436 /******************************************************************************
437 * GdiAlphaBlend [GDI32.@]
439 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
440 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
441 BLENDFUNCTION blendFunction)
443 BOOL ret = FALSE;
444 DC *dcDst, *dcSrc;
446 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
447 /* FIXME: there is a race condition here */
448 if ((dcDst = DC_GetDCUpdate( hdcDst )))
450 dcSrc = DC_GetDCPtr( hdcSrc );
451 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
452 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
453 hdcDst, xDst, yDst, widthDst, heightDst,
454 blendFunction.BlendOp, blendFunction.BlendFlags,
455 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
456 if (dcDst->funcs->pAlphaBlend)
457 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
458 dcSrc ? dcSrc->physDev : NULL,
459 xSrc, ySrc, widthSrc, heightSrc, blendFunction );
460 if (dcSrc) GDI_ReleaseObj( hdcSrc );
461 GDI_ReleaseObj( hdcDst );
463 return ret;
466 /*********************************************************************
467 * PlgBlt [GDI32.@]
470 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
471 HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
472 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
474 FIXME("PlgBlt, stub\n");
475 return 1;