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