ole32: Add tests for error info functions.
[wine/wine-kai.git] / dlls / gdi32 / bitblt.c
blobdf387540fe675acf2aaae84eca41e64ae4d68159
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "gdi_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
32 /***********************************************************************
33 * PatBlt (GDI32.@)
35 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
36 INT width, INT height, DWORD rop)
38 DC * dc = DC_GetDCUpdate( hdc );
39 BOOL bRet = FALSE;
41 if (!dc) return FALSE;
43 if (dc->funcs->pPatBlt)
45 TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
46 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
48 GDI_ReleaseObj( hdc );
49 return bRet;
53 /***********************************************************************
54 * BitBlt (GDI32.@)
56 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
57 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
59 BOOL ret = FALSE;
60 DC *dcDst, *dcSrc;
62 if ((dcDst = DC_GetDCUpdate( hdcDst )) && dcDst->funcs->pBitBlt)
64 GDI_ReleaseObj( hdcDst );
65 /* FIXME: there is a race condition here */
66 dcSrc = DC_GetDCUpdate( hdcSrc );
67 dcDst = DC_GetDCPtr( hdcDst );
68 TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06x\n",
69 hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, rop);
71 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
72 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
74 GDI_ReleaseObj( hdcDst );
75 if (dcSrc) GDI_ReleaseObj( hdcSrc );
77 else if(dcDst && dcDst->funcs->pStretchDIBits)
79 BITMAP bm;
80 BITMAPINFOHEADER info_hdr;
81 HBITMAP hbm;
82 LPVOID bits;
83 INT lines;
85 GDI_ReleaseObj( hdcDst );
87 if(GetObjectType( hdcSrc ) != OBJ_MEMDC)
89 FIXME("hdcSrc isn't a memory dc. Don't yet cope with this\n");
90 return FALSE;
93 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
95 info_hdr.biSize = sizeof(info_hdr);
96 info_hdr.biWidth = bm.bmWidth;
97 info_hdr.biHeight = bm.bmHeight;
98 info_hdr.biPlanes = 1;
99 info_hdr.biBitCount = 32;
100 info_hdr.biCompression = BI_RGB;
101 info_hdr.biSizeImage = 0;
102 info_hdr.biXPelsPerMeter = 0;
103 info_hdr.biYPelsPerMeter = 0;
104 info_hdr.biClrUsed = 0;
105 info_hdr.biClrImportant = 0;
107 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
108 return FALSE;
110 /* Select out the src bitmap before calling GetDIBits */
111 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
112 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
113 SelectObject(hdcSrc, hbm);
115 lines = StretchDIBits(hdcDst, xDst, yDst, width, height, xSrc, bm.bmHeight - height - ySrc,
116 width, height, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
118 HeapFree(GetProcessHeap(), 0, bits);
119 return (lines == height);
121 else if(dcDst)
122 GDI_ReleaseObj( hdcDst );
124 return ret;
128 /***********************************************************************
129 * StretchBlt (GDI32.@)
131 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
132 INT widthDst, INT heightDst,
133 HDC hdcSrc, INT xSrc, INT ySrc,
134 INT widthSrc, INT heightSrc,
135 DWORD rop )
137 BOOL ret = FALSE;
138 DC *dcDst, *dcSrc;
140 if ((dcDst = DC_GetDCUpdate( hdcDst )) && dcDst->funcs->pStretchBlt)
142 GDI_ReleaseObj( hdcDst );
143 /* FIXME: there is a race condition here */
144 if ((dcSrc = DC_GetDCUpdate( hdcSrc )))
146 dcDst = DC_GetDCPtr( hdcDst );
148 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06x\n",
149 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
150 hdcDst, xDst, yDst, widthDst, heightDst, rop );
152 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
153 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
154 rop );
155 GDI_ReleaseObj( hdcDst );
156 GDI_ReleaseObj( hdcSrc );
159 else if(dcDst && dcDst->funcs->pStretchDIBits)
161 BITMAP bm;
162 BITMAPINFOHEADER info_hdr;
163 HBITMAP hbm;
164 LPVOID bits;
165 INT lines;
167 GDI_ReleaseObj( hdcDst );
169 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
171 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
173 info_hdr.biSize = sizeof(info_hdr);
174 info_hdr.biWidth = bm.bmWidth;
175 info_hdr.biHeight = bm.bmHeight;
176 info_hdr.biPlanes = 1;
177 info_hdr.biBitCount = 32;
178 info_hdr.biCompression = BI_RGB;
179 info_hdr.biSizeImage = 0;
180 info_hdr.biXPelsPerMeter = 0;
181 info_hdr.biYPelsPerMeter = 0;
182 info_hdr.biClrUsed = 0;
183 info_hdr.biClrImportant = 0;
185 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
186 return FALSE;
188 /* Select out the src bitmap before calling GetDIBits */
189 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
190 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
191 SelectObject(hdcSrc, hbm);
193 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
194 widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
196 HeapFree(GetProcessHeap(), 0, bits);
197 return (lines == heightSrc);
199 else if(dcDst)
200 GDI_ReleaseObj( hdcDst );
202 return ret;
205 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
206 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
208 /***********************************************************************
209 * MaskBlt [GDI32.@]
211 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
212 INT nWidth, INT nHeight, HDC hdcSrc,
213 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
214 INT xMask, INT yMask, DWORD dwRop)
216 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
217 HDC hDC1, hDC2;
218 HBRUSH hbrMask, hbrDst, hbrTmp;
220 static const DWORD ROP3Table[256] =
222 0x00000042, 0x00010289,
223 0x00020C89, 0x000300AA,
224 0x00040C88, 0x000500A9,
225 0x00060865, 0x000702C5,
226 0x00080F08, 0x00090245,
227 0x000A0329, 0x000B0B2A,
228 0x000C0324, 0x000D0B25,
229 0x000E08A5, 0x000F0001,
230 0x00100C85, 0x001100A6,
231 0x00120868, 0x001302C8,
232 0x00140869, 0x001502C9,
233 0x00165CCA, 0x00171D54,
234 0x00180D59, 0x00191CC8,
235 0x001A06C5, 0x001B0768,
236 0x001C06CA, 0x001D0766,
237 0x001E01A5, 0x001F0385,
238 0x00200F09, 0x00210248,
239 0x00220326, 0x00230B24,
240 0x00240D55, 0x00251CC5,
241 0x002606C8, 0x00271868,
242 0x00280369, 0x002916CA,
243 0x002A0CC9, 0x002B1D58,
244 0x002C0784, 0x002D060A,
245 0x002E064A, 0x002F0E2A,
246 0x0030032A, 0x00310B28,
247 0x00320688, 0x00330008,
248 0x003406C4, 0x00351864,
249 0x003601A8, 0x00370388,
250 0x0038078A, 0x00390604,
251 0x003A0644, 0x003B0E24,
252 0x003C004A, 0x003D18A4,
253 0x003E1B24, 0x003F00EA,
254 0x00400F0A, 0x00410249,
255 0x00420D5D, 0x00431CC4,
256 0x00440328, 0x00450B29,
257 0x004606C6, 0x0047076A,
258 0x00480368, 0x004916C5,
259 0x004A0789, 0x004B0605,
260 0x004C0CC8, 0x004D1954,
261 0x004E0645, 0x004F0E25,
262 0x00500325, 0x00510B26,
263 0x005206C9, 0x00530764,
264 0x005408A9, 0x00550009,
265 0x005601A9, 0x00570389,
266 0x00580785, 0x00590609,
267 0x005A0049, 0x005B18A9,
268 0x005C0649, 0x005D0E29,
269 0x005E1B29, 0x005F00E9,
270 0x00600365, 0x006116C6,
271 0x00620786, 0x00630608,
272 0x00640788, 0x00650606,
273 0x00660046, 0x006718A8,
274 0x006858A6, 0x00690145,
275 0x006A01E9, 0x006B178A,
276 0x006C01E8, 0x006D1785,
277 0x006E1E28, 0x006F0C65,
278 0x00700CC5, 0x00711D5C,
279 0x00720648, 0x00730E28,
280 0x00740646, 0x00750E26,
281 0x00761B28, 0x007700E6,
282 0x007801E5, 0x00791786,
283 0x007A1E29, 0x007B0C68,
284 0x007C1E24, 0x007D0C69,
285 0x007E0955, 0x007F03C9,
286 0x008003E9, 0x00810975,
287 0x00820C49, 0x00831E04,
288 0x00840C48, 0x00851E05,
289 0x008617A6, 0x008701C5,
290 0x008800C6, 0x00891B08,
291 0x008A0E06, 0x008B0666,
292 0x008C0E08, 0x008D0668,
293 0x008E1D7C, 0x008F0CE5,
294 0x00900C45, 0x00911E08,
295 0x009217A9, 0x009301C4,
296 0x009417AA, 0x009501C9,
297 0x00960169, 0x0097588A,
298 0x00981888, 0x00990066,
299 0x009A0709, 0x009B07A8,
300 0x009C0704, 0x009D07A6,
301 0x009E16E6, 0x009F0345,
302 0x00A000C9, 0x00A11B05,
303 0x00A20E09, 0x00A30669,
304 0x00A41885, 0x00A50065,
305 0x00A60706, 0x00A707A5,
306 0x00A803A9, 0x00A90189,
307 0x00AA0029, 0x00AB0889,
308 0x00AC0744, 0x00AD06E9,
309 0x00AE0B06, 0x00AF0229,
310 0x00B00E05, 0x00B10665,
311 0x00B21974, 0x00B30CE8,
312 0x00B4070A, 0x00B507A9,
313 0x00B616E9, 0x00B70348,
314 0x00B8074A, 0x00B906E6,
315 0x00BA0B09, 0x00BB0226,
316 0x00BC1CE4, 0x00BD0D7D,
317 0x00BE0269, 0x00BF08C9,
318 0x00C000CA, 0x00C11B04,
319 0x00C21884, 0x00C3006A,
320 0x00C40E04, 0x00C50664,
321 0x00C60708, 0x00C707AA,
322 0x00C803A8, 0x00C90184,
323 0x00CA0749, 0x00CB06E4,
324 0x00CC0020, 0x00CD0888,
325 0x00CE0B08, 0x00CF0224,
326 0x00D00E0A, 0x00D1066A,
327 0x00D20705, 0x00D307A4,
328 0x00D41D78, 0x00D50CE9,
329 0x00D616EA, 0x00D70349,
330 0x00D80745, 0x00D906E8,
331 0x00DA1CE9, 0x00DB0D75,
332 0x00DC0B04, 0x00DD0228,
333 0x00DE0268, 0x00DF08C8,
334 0x00E003A5, 0x00E10185,
335 0x00E20746, 0x00E306EA,
336 0x00E40748, 0x00E506E5,
337 0x00E61CE8, 0x00E70D79,
338 0x00E81D74, 0x00E95CE6,
339 0x00EA02E9, 0x00EB0849,
340 0x00EC02E8, 0x00ED0848,
341 0x00EE0086, 0x00EF0A08,
342 0x00F00021, 0x00F10885,
343 0x00F20B05, 0x00F3022A,
344 0x00F40B0A, 0x00F50225,
345 0x00F60265, 0x00F708C5,
346 0x00F802E5, 0x00F90845,
347 0x00FA0089, 0x00FB0A09,
348 0x00FC008A, 0x00FD0A0A,
349 0x00FE02A9, 0x00FF0062,
352 if (!hbmMask)
353 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
355 hbrMask = CreatePatternBrush(hbmMask);
356 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
358 /* make bitmap */
359 hDC1 = CreateCompatibleDC(hdcDest);
360 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
361 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
363 /* draw using bkgnd rop */
364 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
365 hbrTmp = SelectObject(hDC1, hbrDst);
366 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
367 SelectObject(hDC1, hbrTmp);
369 /* make bitmap */
370 hDC2 = CreateCompatibleDC(hdcDest);
371 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
372 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
374 /* draw using foregnd rop */
375 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
376 hbrTmp = SelectObject(hDC2, hbrDst);
377 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
379 /* combine both using the mask as a pattern brush */
380 SelectObject(hDC2, hbrMask);
381 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
382 SelectObject(hDC2, hbrTmp);
384 /* blit to dst */
385 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
387 /* restore all objects */
388 SelectObject(hdcDest, hbrDst);
389 SelectObject(hDC1, hOldBitmap1);
390 SelectObject(hDC2, hOldBitmap2);
392 /* delete all temp objects */
393 DeleteObject(hBitmap1);
394 DeleteObject(hBitmap2);
395 DeleteObject(hbrMask);
397 DeleteDC(hDC1);
398 DeleteDC(hDC2);
400 return TRUE;
403 /******************************************************************************
404 * GdiTransparentBlt [GDI32.@]
406 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
407 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
408 UINT crTransparent )
410 BOOL ret = FALSE;
411 HDC hdcWork;
412 HBITMAP bmpWork;
413 HGDIOBJ oldWork;
414 HDC hdcMask = NULL;
415 HBITMAP bmpMask = NULL;
416 HBITMAP oldMask = NULL;
417 COLORREF oldBackground;
418 COLORREF oldForeground;
419 int oldStretchMode;
421 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
422 TRACE("Cannot mirror\n");
423 return FALSE;
426 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
427 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
429 /* Stretch bitmap */
430 oldStretchMode = GetStretchBltMode(hdcSrc);
431 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
432 SetStretchBltMode(hdcSrc, COLORONCOLOR);
433 hdcWork = CreateCompatibleDC(hdcDest);
434 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
435 oldWork = SelectObject(hdcWork, bmpWork);
436 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
437 TRACE("Failed to stretch\n");
438 goto error;
440 SetBkColor(hdcWork, crTransparent);
442 /* Create mask */
443 hdcMask = CreateCompatibleDC(hdcDest);
444 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
445 oldMask = SelectObject(hdcMask, bmpMask);
446 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
447 TRACE("Failed to create mask\n");
448 goto error;
451 /* Replace transparent color with black */
452 SetBkColor(hdcWork, RGB(0,0,0));
453 SetTextColor(hdcWork, RGB(255,255,255));
454 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
455 TRACE("Failed to mask out background\n");
456 goto error;
459 /* Replace non-transparent area on destination with black */
460 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
461 TRACE("Failed to clear destination area\n");
462 goto error;
465 /* Draw the image */
466 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
467 TRACE("Failed to paint image\n");
468 goto error;
471 ret = TRUE;
472 error:
473 SetStretchBltMode(hdcSrc, oldStretchMode);
474 SetBkColor(hdcDest, oldBackground);
475 SetTextColor(hdcDest, oldForeground);
476 if(hdcWork) {
477 SelectObject(hdcWork, oldWork);
478 DeleteDC(hdcWork);
480 if(bmpWork) DeleteObject(bmpWork);
481 if(hdcMask) {
482 SelectObject(hdcMask, oldMask);
483 DeleteDC(hdcMask);
485 if(bmpMask) DeleteObject(bmpMask);
486 return ret;
489 /******************************************************************************
490 * GdiAlphaBlend [GDI32.@]
492 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
493 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
494 BLENDFUNCTION blendFunction)
496 BOOL ret = FALSE;
497 DC *dcDst, *dcSrc;
499 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
500 /* FIXME: there is a race condition here */
501 if ((dcDst = DC_GetDCUpdate( hdcDst )))
503 dcSrc = DC_GetDCPtr( hdcSrc );
504 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
505 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
506 hdcDst, xDst, yDst, widthDst, heightDst,
507 blendFunction.BlendOp, blendFunction.BlendFlags,
508 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
509 if (dcDst->funcs->pAlphaBlend)
510 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
511 dcSrc ? dcSrc->physDev : NULL,
512 xSrc, ySrc, widthSrc, heightSrc, blendFunction );
513 if (dcSrc) GDI_ReleaseObj( hdcSrc );
514 GDI_ReleaseObj( hdcDst );
516 return ret;
519 /*********************************************************************
520 * PlgBlt [GDI32.@]
523 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
524 HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
525 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
527 FIXME("PlgBlt, stub\n");
528 return 1;