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