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