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