winecoreaudio.drv: Add mmdevapi driver.
[wine/multimedia.git] / dlls / gdi32 / bitblt.c
blob6c556d7acbf7d4ff6caf37ac2532c9b08f214ffd
1 /*
2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
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.
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.
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
21 #include "config.h"
23 #include <stdarg.h>
25 #include <math.h>
26 #ifdef HAVE_FLOAT_H
27 #include <float.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "gdi_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
38 static inline BOOL rop_uses_src( DWORD rop )
40 return ((rop >> 2) & 0x330000) != (rop & 0x330000);
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 )
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];
56 /* make sure we have a real implementation for StretchDIBits */
57 if (GET_DC_PHYSDEV( dc, pStretchDIBits ) == dst_dev) return 0;
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;
69 if (GetObjectType( src_dev->hdc ) != OBJ_MEMDC) return FALSE;
70 if (!GetObjectW( GetCurrentObject( src_dev->hdc, OBJ_BITMAP ), sizeof(bm), &bm )) return FALSE;
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;
84 if (!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
85 return FALSE;
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 );
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);
99 /***********************************************************************
100 * PatBlt (GDI32.@)
102 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop)
104 DC * dc;
105 BOOL bRet = FALSE;
107 TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
109 if (rop_uses_src( rop )) return FALSE;
110 if ((dc = get_dc_ptr( hdc )))
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 );
117 return bRet;
121 /***********************************************************************
122 * BitBlt (GDI32.@)
124 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
125 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
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 );
133 /***********************************************************************
134 * StretchBlt (GDI32.@)
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 )
139 BOOL ret = FALSE;
140 DC *dcDst, *dcSrc;
142 if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
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 );
148 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
150 if ((dcSrc = get_dc_ptr( hdcSrc )))
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 );
160 release_dc_ptr( dcDst );
161 return ret;
164 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
165 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
167 /***********************************************************************
168 * MaskBlt [GDI32.@]
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)
175 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
176 HDC hDC1, hDC2;
177 HBRUSH hbrMask, hbrDst, hbrTmp;
179 static const DWORD ROP3Table[256] =
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,
311 if (!hbmMask)
312 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
314 hbrMask = CreatePatternBrush(hbmMask);
315 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
317 /* make bitmap */
318 hDC1 = CreateCompatibleDC(hdcDest);
319 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
320 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
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);
328 /* make bitmap */
329 hDC2 = CreateCompatibleDC(hdcDest);
330 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
331 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
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));
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);
343 /* blit to dst */
344 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
346 /* restore all objects */
347 SelectObject(hdcDest, hbrDst);
348 SelectObject(hDC1, hOldBitmap1);
349 SelectObject(hDC2, hOldBitmap2);
351 /* delete all temp objects */
352 DeleteObject(hBitmap1);
353 DeleteObject(hBitmap2);
354 DeleteObject(hbrMask);
356 DeleteDC(hDC1);
357 DeleteDC(hDC2);
359 return TRUE;
362 /******************************************************************************
363 * GdiTransparentBlt [GDI32.@]
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 )
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;
380 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
381 TRACE("Cannot mirror\n");
382 return FALSE;
385 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
386 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
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;
399 SetBkColor(hdcWork, crTransparent);
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;
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;
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;
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;
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);
439 if(bmpWork) DeleteObject(bmpWork);
440 if(hdcMask) {
441 SelectObject(hdcMask, oldMask);
442 DeleteDC(hdcMask);
444 if(bmpMask) DeleteObject(bmpMask);
445 return ret;
448 /******************************************************************************
449 * GdiAlphaBlend [GDI32.@]
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)
455 BOOL ret = FALSE;
456 DC *dcDst, *dcSrc;
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 );
463 dcSrc = get_dc_ptr( hdcSrc );
464 if (!dcSrc) return FALSE;
466 if ((dcDst = get_dc_ptr( hdcDst )))
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 );
476 release_dc_ptr( dcSrc );
477 return ret;
480 /*********************************************************************
481 * PlgBlt [GDI32.@]
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)
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;
498 /* save actual mode, set GM_ADVANCED */
499 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
500 if (oldgMode == 0)
501 return FALSE;
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);
514 if (fabs(det) < 1e-5)
516 SetGraphicsMode(hdcDest,oldgMode);
517 return FALSE;
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);
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;
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;
539 GetWorldTransform(hdcSrc,&SrcXf);
540 CombineTransform(&xf,&xf,&SrcXf);
542 /* save actual dest transform */
543 GetWorldTransform(hdcDest,&oldDestXf);
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);
555 return TRUE;