kernel32: Don't use HIWORD to check for swapped args in GetCurrentDirectoryA.
[wine.git] / dlls / gdi32 / bitblt.c
blobf638a7383338ba9fdebe299085d986df1669e7ef
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 "config.h"
23 #include <stdarg.h>
25 #include <math.h>
26 #ifdef HAVE_FLOAT_H
27 #include <float.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "gdi_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
39 /***********************************************************************
40 * PatBlt (GDI32.@)
42 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
43 INT width, INT height, DWORD rop)
45 DC * dc = get_dc_ptr( hdc );
46 BOOL bRet = FALSE;
48 if (!dc) return FALSE;
50 TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
52 if (dc->funcs->pPatBlt)
54 update_dc( dc );
55 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
57 else if (dc->funcs->pStretchBlt)
59 update_dc( dc );
60 bRet = dc->funcs->pStretchBlt( dc->physDev, left, top, width, height, NULL, 0, 0, 0, 0, rop );
62 release_dc_ptr( dc );
63 return bRet;
67 /***********************************************************************
68 * BitBlt (GDI32.@)
70 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
71 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
73 BOOL ret = FALSE;
74 DC *dcDst, *dcSrc;
76 TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06x\n",
77 hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, rop);
79 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
81 if (dcDst->funcs->pBitBlt || dcDst->funcs->pStretchBlt)
83 update_dc( dcDst );
84 dcSrc = get_dc_ptr( hdcSrc );
85 if (dcSrc) update_dc( dcSrc );
87 if (dcDst->funcs->pBitBlt)
88 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
89 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
90 else
91 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, width, height,
92 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc,
93 width, height, rop );
95 release_dc_ptr( dcDst );
96 if (dcSrc) release_dc_ptr( dcSrc );
98 else if (dcDst->funcs->pStretchDIBits)
100 BITMAP bm;
101 BITMAPINFOHEADER info_hdr;
102 HBITMAP hbm;
103 LPVOID bits;
104 INT lines;
106 release_dc_ptr( dcDst );
108 if(GetObjectType( hdcSrc ) != OBJ_MEMDC)
110 FIXME("hdcSrc isn't a memory dc. Don't yet cope with this\n");
111 return FALSE;
114 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
116 info_hdr.biSize = sizeof(info_hdr);
117 info_hdr.biWidth = bm.bmWidth;
118 info_hdr.biHeight = bm.bmHeight;
119 info_hdr.biPlanes = 1;
120 info_hdr.biBitCount = 32;
121 info_hdr.biCompression = BI_RGB;
122 info_hdr.biSizeImage = 0;
123 info_hdr.biXPelsPerMeter = 0;
124 info_hdr.biYPelsPerMeter = 0;
125 info_hdr.biClrUsed = 0;
126 info_hdr.biClrImportant = 0;
128 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
129 return FALSE;
131 /* Select out the src bitmap before calling GetDIBits */
132 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
133 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
134 SelectObject(hdcSrc, hbm);
136 lines = StretchDIBits(hdcDst, xDst, yDst, width, height, xSrc, bm.bmHeight - height - ySrc,
137 width, height, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
139 HeapFree(GetProcessHeap(), 0, bits);
140 return (lines == height);
142 else release_dc_ptr( dcDst );
144 return ret;
148 /***********************************************************************
149 * StretchBlt (GDI32.@)
151 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
152 INT widthDst, INT heightDst,
153 HDC hdcSrc, INT xSrc, INT ySrc,
154 INT widthSrc, INT heightSrc,
155 DWORD rop )
157 BOOL ret = FALSE;
158 DC *dcDst, *dcSrc;
160 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06x\n",
161 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
162 hdcDst, xDst, yDst, widthDst, heightDst, rop );
165 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
167 if (dcDst->funcs->pStretchBlt)
169 if ((dcSrc = get_dc_ptr( hdcSrc )))
171 update_dc( dcDst );
172 update_dc( dcSrc );
174 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
175 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
176 rop );
177 release_dc_ptr( dcDst );
178 release_dc_ptr( dcSrc );
181 else if (dcDst->funcs->pStretchDIBits)
183 BITMAP bm;
184 BITMAPINFOHEADER info_hdr;
185 HBITMAP hbm;
186 LPVOID bits;
187 INT lines;
188 POINT pts[2];
190 pts[0].x = xSrc;
191 pts[0].y = ySrc;
192 pts[1].x = xSrc + widthSrc;
193 pts[1].y = ySrc + heightSrc;
194 LPtoDP(hdcSrc, pts, 2);
195 xSrc = pts[0].x;
196 ySrc = pts[0].y;
197 widthSrc = pts[1].x - pts[0].x;
198 heightSrc = pts[1].y - pts[0].y;
200 release_dc_ptr( dcDst );
202 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
204 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
206 info_hdr.biSize = sizeof(info_hdr);
207 info_hdr.biWidth = bm.bmWidth;
208 info_hdr.biHeight = bm.bmHeight;
209 info_hdr.biPlanes = 1;
210 info_hdr.biBitCount = 32;
211 info_hdr.biCompression = BI_RGB;
212 info_hdr.biSizeImage = 0;
213 info_hdr.biXPelsPerMeter = 0;
214 info_hdr.biYPelsPerMeter = 0;
215 info_hdr.biClrUsed = 0;
216 info_hdr.biClrImportant = 0;
218 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
219 return FALSE;
221 /* Select out the src bitmap before calling GetDIBits */
222 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
223 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
224 SelectObject(hdcSrc, hbm);
226 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
227 widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
229 HeapFree(GetProcessHeap(), 0, bits);
230 return (lines == heightSrc);
232 else release_dc_ptr( dcDst );
234 return ret;
237 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
238 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
240 /***********************************************************************
241 * MaskBlt [GDI32.@]
243 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
244 INT nWidth, INT nHeight, HDC hdcSrc,
245 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
246 INT xMask, INT yMask, DWORD dwRop)
248 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
249 HDC hDC1, hDC2;
250 HBRUSH hbrMask, hbrDst, hbrTmp;
252 static const DWORD ROP3Table[256] =
254 0x00000042, 0x00010289,
255 0x00020C89, 0x000300AA,
256 0x00040C88, 0x000500A9,
257 0x00060865, 0x000702C5,
258 0x00080F08, 0x00090245,
259 0x000A0329, 0x000B0B2A,
260 0x000C0324, 0x000D0B25,
261 0x000E08A5, 0x000F0001,
262 0x00100C85, 0x001100A6,
263 0x00120868, 0x001302C8,
264 0x00140869, 0x001502C9,
265 0x00165CCA, 0x00171D54,
266 0x00180D59, 0x00191CC8,
267 0x001A06C5, 0x001B0768,
268 0x001C06CA, 0x001D0766,
269 0x001E01A5, 0x001F0385,
270 0x00200F09, 0x00210248,
271 0x00220326, 0x00230B24,
272 0x00240D55, 0x00251CC5,
273 0x002606C8, 0x00271868,
274 0x00280369, 0x002916CA,
275 0x002A0CC9, 0x002B1D58,
276 0x002C0784, 0x002D060A,
277 0x002E064A, 0x002F0E2A,
278 0x0030032A, 0x00310B28,
279 0x00320688, 0x00330008,
280 0x003406C4, 0x00351864,
281 0x003601A8, 0x00370388,
282 0x0038078A, 0x00390604,
283 0x003A0644, 0x003B0E24,
284 0x003C004A, 0x003D18A4,
285 0x003E1B24, 0x003F00EA,
286 0x00400F0A, 0x00410249,
287 0x00420D5D, 0x00431CC4,
288 0x00440328, 0x00450B29,
289 0x004606C6, 0x0047076A,
290 0x00480368, 0x004916C5,
291 0x004A0789, 0x004B0605,
292 0x004C0CC8, 0x004D1954,
293 0x004E0645, 0x004F0E25,
294 0x00500325, 0x00510B26,
295 0x005206C9, 0x00530764,
296 0x005408A9, 0x00550009,
297 0x005601A9, 0x00570389,
298 0x00580785, 0x00590609,
299 0x005A0049, 0x005B18A9,
300 0x005C0649, 0x005D0E29,
301 0x005E1B29, 0x005F00E9,
302 0x00600365, 0x006116C6,
303 0x00620786, 0x00630608,
304 0x00640788, 0x00650606,
305 0x00660046, 0x006718A8,
306 0x006858A6, 0x00690145,
307 0x006A01E9, 0x006B178A,
308 0x006C01E8, 0x006D1785,
309 0x006E1E28, 0x006F0C65,
310 0x00700CC5, 0x00711D5C,
311 0x00720648, 0x00730E28,
312 0x00740646, 0x00750E26,
313 0x00761B28, 0x007700E6,
314 0x007801E5, 0x00791786,
315 0x007A1E29, 0x007B0C68,
316 0x007C1E24, 0x007D0C69,
317 0x007E0955, 0x007F03C9,
318 0x008003E9, 0x00810975,
319 0x00820C49, 0x00831E04,
320 0x00840C48, 0x00851E05,
321 0x008617A6, 0x008701C5,
322 0x008800C6, 0x00891B08,
323 0x008A0E06, 0x008B0666,
324 0x008C0E08, 0x008D0668,
325 0x008E1D7C, 0x008F0CE5,
326 0x00900C45, 0x00911E08,
327 0x009217A9, 0x009301C4,
328 0x009417AA, 0x009501C9,
329 0x00960169, 0x0097588A,
330 0x00981888, 0x00990066,
331 0x009A0709, 0x009B07A8,
332 0x009C0704, 0x009D07A6,
333 0x009E16E6, 0x009F0345,
334 0x00A000C9, 0x00A11B05,
335 0x00A20E09, 0x00A30669,
336 0x00A41885, 0x00A50065,
337 0x00A60706, 0x00A707A5,
338 0x00A803A9, 0x00A90189,
339 0x00AA0029, 0x00AB0889,
340 0x00AC0744, 0x00AD06E9,
341 0x00AE0B06, 0x00AF0229,
342 0x00B00E05, 0x00B10665,
343 0x00B21974, 0x00B30CE8,
344 0x00B4070A, 0x00B507A9,
345 0x00B616E9, 0x00B70348,
346 0x00B8074A, 0x00B906E6,
347 0x00BA0B09, 0x00BB0226,
348 0x00BC1CE4, 0x00BD0D7D,
349 0x00BE0269, 0x00BF08C9,
350 0x00C000CA, 0x00C11B04,
351 0x00C21884, 0x00C3006A,
352 0x00C40E04, 0x00C50664,
353 0x00C60708, 0x00C707AA,
354 0x00C803A8, 0x00C90184,
355 0x00CA0749, 0x00CB06E4,
356 0x00CC0020, 0x00CD0888,
357 0x00CE0B08, 0x00CF0224,
358 0x00D00E0A, 0x00D1066A,
359 0x00D20705, 0x00D307A4,
360 0x00D41D78, 0x00D50CE9,
361 0x00D616EA, 0x00D70349,
362 0x00D80745, 0x00D906E8,
363 0x00DA1CE9, 0x00DB0D75,
364 0x00DC0B04, 0x00DD0228,
365 0x00DE0268, 0x00DF08C8,
366 0x00E003A5, 0x00E10185,
367 0x00E20746, 0x00E306EA,
368 0x00E40748, 0x00E506E5,
369 0x00E61CE8, 0x00E70D79,
370 0x00E81D74, 0x00E95CE6,
371 0x00EA02E9, 0x00EB0849,
372 0x00EC02E8, 0x00ED0848,
373 0x00EE0086, 0x00EF0A08,
374 0x00F00021, 0x00F10885,
375 0x00F20B05, 0x00F3022A,
376 0x00F40B0A, 0x00F50225,
377 0x00F60265, 0x00F708C5,
378 0x00F802E5, 0x00F90845,
379 0x00FA0089, 0x00FB0A09,
380 0x00FC008A, 0x00FD0A0A,
381 0x00FE02A9, 0x00FF0062,
384 if (!hbmMask)
385 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
387 hbrMask = CreatePatternBrush(hbmMask);
388 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
390 /* make bitmap */
391 hDC1 = CreateCompatibleDC(hdcDest);
392 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
393 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
395 /* draw using bkgnd rop */
396 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
397 hbrTmp = SelectObject(hDC1, hbrDst);
398 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
399 SelectObject(hDC1, hbrTmp);
401 /* make bitmap */
402 hDC2 = CreateCompatibleDC(hdcDest);
403 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
404 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
406 /* draw using foregnd rop */
407 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
408 hbrTmp = SelectObject(hDC2, hbrDst);
409 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
411 /* combine both using the mask as a pattern brush */
412 SelectObject(hDC2, hbrMask);
413 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
414 SelectObject(hDC2, hbrTmp);
416 /* blit to dst */
417 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
419 /* restore all objects */
420 SelectObject(hdcDest, hbrDst);
421 SelectObject(hDC1, hOldBitmap1);
422 SelectObject(hDC2, hOldBitmap2);
424 /* delete all temp objects */
425 DeleteObject(hBitmap1);
426 DeleteObject(hBitmap2);
427 DeleteObject(hbrMask);
429 DeleteDC(hDC1);
430 DeleteDC(hDC2);
432 return TRUE;
435 /******************************************************************************
436 * GdiTransparentBlt [GDI32.@]
438 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
439 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
440 UINT crTransparent )
442 BOOL ret = FALSE;
443 HDC hdcWork;
444 HBITMAP bmpWork;
445 HGDIOBJ oldWork;
446 HDC hdcMask = NULL;
447 HBITMAP bmpMask = NULL;
448 HBITMAP oldMask = NULL;
449 COLORREF oldBackground;
450 COLORREF oldForeground;
451 int oldStretchMode;
453 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
454 TRACE("Cannot mirror\n");
455 return FALSE;
458 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
459 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
461 /* Stretch bitmap */
462 oldStretchMode = GetStretchBltMode(hdcSrc);
463 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
464 SetStretchBltMode(hdcSrc, COLORONCOLOR);
465 hdcWork = CreateCompatibleDC(hdcDest);
466 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
467 oldWork = SelectObject(hdcWork, bmpWork);
468 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
469 TRACE("Failed to stretch\n");
470 goto error;
472 SetBkColor(hdcWork, crTransparent);
474 /* Create mask */
475 hdcMask = CreateCompatibleDC(hdcDest);
476 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
477 oldMask = SelectObject(hdcMask, bmpMask);
478 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
479 TRACE("Failed to create mask\n");
480 goto error;
483 /* Replace transparent color with black */
484 SetBkColor(hdcWork, RGB(0,0,0));
485 SetTextColor(hdcWork, RGB(255,255,255));
486 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
487 TRACE("Failed to mask out background\n");
488 goto error;
491 /* Replace non-transparent area on destination with black */
492 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
493 TRACE("Failed to clear destination area\n");
494 goto error;
497 /* Draw the image */
498 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
499 TRACE("Failed to paint image\n");
500 goto error;
503 ret = TRUE;
504 error:
505 SetStretchBltMode(hdcSrc, oldStretchMode);
506 SetBkColor(hdcDest, oldBackground);
507 SetTextColor(hdcDest, oldForeground);
508 if(hdcWork) {
509 SelectObject(hdcWork, oldWork);
510 DeleteDC(hdcWork);
512 if(bmpWork) DeleteObject(bmpWork);
513 if(hdcMask) {
514 SelectObject(hdcMask, oldMask);
515 DeleteDC(hdcMask);
517 if(bmpMask) DeleteObject(bmpMask);
518 return ret;
521 /******************************************************************************
522 * GdiAlphaBlend [GDI32.@]
524 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
525 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
526 BLENDFUNCTION blendFunction)
528 BOOL ret = FALSE;
529 DC *dcDst, *dcSrc;
531 dcSrc = get_dc_ptr( hdcSrc );
532 if (!dcSrc) return FALSE;
534 if ((dcDst = get_dc_ptr( hdcDst )))
536 update_dc( dcSrc );
537 update_dc( dcDst );
538 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
539 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
540 hdcDst, xDst, yDst, widthDst, heightDst,
541 blendFunction.BlendOp, blendFunction.BlendFlags,
542 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
543 if (dcDst->funcs->pAlphaBlend)
544 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
545 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
546 blendFunction );
547 release_dc_ptr( dcDst );
549 release_dc_ptr( dcSrc );
550 return ret;
553 /*********************************************************************
554 * PlgBlt [GDI32.@]
557 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
558 HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
559 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
561 int oldgMode;
562 /* parallelogram coords */
563 POINT plg[3];
564 /* rect coords */
565 POINT rect[3];
566 XFORM xf;
567 XFORM SrcXf;
568 XFORM oldDestXf;
569 double det;
571 /* save actual mode, set GM_ADVANCED */
572 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
573 if (oldgMode == 0)
574 return FALSE;
576 memcpy(plg,lpPoint,sizeof(POINT)*3);
577 rect[0].x = nXSrc;
578 rect[0].y = nYSrc;
579 rect[1].x = nXSrc + nWidth;
580 rect[1].y = nYSrc;
581 rect[2].x = nXSrc;
582 rect[2].y = nYSrc + nHeight;
583 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
584 /* determinant */
585 det = rect[1].x*(rect[2].y - rect[0].y) - rect[2].x*(rect[1].y - rect[0].y) - rect[0].x*(rect[2].y - rect[1].y);
587 if (fabs(det) < 1e-5)
589 SetGraphicsMode(hdcDest,oldgMode);
590 return FALSE;
593 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
594 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
596 /* X components */
597 xf.eM11 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det;
598 xf.eM21 = (rect[1].x*(plg[2].x - plg[0].x) - rect[2].x*(plg[1].x - plg[0].x) - rect[0].x*(plg[2].x - plg[1].x)) / det;
599 xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
600 rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
601 rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
602 ) / det;
604 /* Y components */
605 xf.eM12 = (plg[1].y*(rect[2].y - rect[0].y) - plg[2].y*(rect[1].y - rect[0].y) - plg[0].y*(rect[2].y - rect[1].y)) / det;
606 xf.eM22 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det;
607 xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
608 rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
609 rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
610 ) / det;
612 GetWorldTransform(hdcSrc,&SrcXf);
613 CombineTransform(&xf,&xf,&SrcXf);
615 /* save actual dest transform */
616 GetWorldTransform(hdcDest,&oldDestXf);
618 SetWorldTransform(hdcDest,&xf);
619 /* now destination and source DCs use same coords */
620 MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
621 hdcSrc, nXSrc,nYSrc,
622 hbmMask,xMask,yMask,
623 SRCCOPY);
624 /* restore dest DC */
625 SetWorldTransform(hdcDest,&oldDestXf);
626 SetGraphicsMode(hdcDest,oldgMode);
628 return TRUE;