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