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