- Create another branch for networking fixes
[reactos.git] / subsystems / win32 / win32k / objects / bitblt.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* $Id: bitmaps.c 28300 2007-08-12 15:20:09Z tkreuzer $ */
20
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26
27
28 BOOL APIENTRY
29 NtGdiAlphaBlend(
30 HDC hDCDest,
31 LONG XOriginDest,
32 LONG YOriginDest,
33 LONG WidthDest,
34 LONG HeightDest,
35 HDC hDCSrc,
36 LONG XOriginSrc,
37 LONG YOriginSrc,
38 LONG WidthSrc,
39 LONG HeightSrc,
40 BLENDFUNCTION BlendFunc,
41 HANDLE hcmXform)
42 {
43 PDC DCDest;
44 PDC DCSrc;
45 SURFACE *BitmapDest, *BitmapSrc;
46 RECTL DestRect, SourceRect;
47 BOOL bResult;
48 EXLATEOBJ exlo;
49 BLENDOBJ BlendObj;
50 BlendObj.BlendFunction = BlendFunc;
51
52 if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
53 {
54 SetLastWin32Error(ERROR_INVALID_PARAMETER);
55 return FALSE;
56 }
57
58 DCDest = DC_LockDc(hDCDest);
59 if (NULL == DCDest)
60 {
61 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
62 SetLastWin32Error(ERROR_INVALID_HANDLE);
63 return FALSE;
64 }
65
66 if (DCDest->dctype == DC_TYPE_INFO)
67 {
68 DC_UnlockDc(DCDest);
69 /* Yes, Windows really returns TRUE in this case */
70 return TRUE;
71 }
72
73 if (hDCSrc != hDCDest)
74 {
75 DCSrc = DC_LockDc(hDCSrc);
76 if (NULL == DCSrc)
77 {
78 DC_UnlockDc(DCDest);
79 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
80 SetLastWin32Error(ERROR_INVALID_HANDLE);
81 return FALSE;
82 }
83
84 if (DCSrc->dctype == DC_TYPE_INFO)
85 {
86 DC_UnlockDc(DCSrc);
87 DC_UnlockDc(DCDest);
88 /* Yes, Windows really returns TRUE in this case */
89 return TRUE;
90 }
91 }
92 else
93 {
94 DCSrc = DCDest;
95 }
96
97 DestRect.left = XOriginDest;
98 DestRect.top = YOriginDest;
99 DestRect.right = XOriginDest + WidthDest;
100 DestRect.bottom = YOriginDest + HeightDest;
101 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
102
103 DestRect.left += DCDest->ptlDCOrig.x;
104 DestRect.top += DCDest->ptlDCOrig.y;
105 DestRect.right += DCDest->ptlDCOrig.x;
106 DestRect.bottom += DCDest->ptlDCOrig.y;
107
108 SourceRect.left = XOriginSrc;
109 SourceRect.top = YOriginSrc;
110 SourceRect.right = XOriginSrc + WidthSrc;
111 SourceRect.bottom = YOriginSrc + HeightSrc;
112 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
113
114 SourceRect.left += DCSrc->ptlDCOrig.x;
115 SourceRect.top += DCSrc->ptlDCOrig.y;
116 SourceRect.right += DCSrc->ptlDCOrig.x;
117 SourceRect.bottom += DCSrc->ptlDCOrig.y;
118
119 if (!DestRect.right ||
120 !DestRect.bottom ||
121 !SourceRect.right ||
122 !SourceRect.bottom)
123 {
124 if (hDCSrc != hDCDest)
125 DC_UnlockDc(DCSrc);
126 DC_UnlockDc(DCDest);
127 return TRUE;
128 }
129
130 /* Determine surfaces to be used in the bitblt */
131 BitmapDest = DCDest->dclevel.pSurface;
132 if (!BitmapDest)
133 {
134 if (hDCSrc != hDCDest)
135 DC_UnlockDc(DCSrc);
136 DC_UnlockDc(DCDest);
137 return FALSE;
138 }
139
140 BitmapSrc = DCSrc->dclevel.pSurface;
141 if (!BitmapSrc)
142 {
143 if (hDCSrc != hDCDest)
144 DC_UnlockDc(DCSrc);
145 DC_UnlockDc(DCDest);
146 return FALSE;
147 }
148
149 /* Create the XLATEOBJ. */
150 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
151
152 /* Perform the alpha blend operation */
153 bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
154 &BitmapSrc->SurfObj,
155 DCDest->rosdc.CombinedClip,
156 &exlo.xlo,
157 &DestRect,
158 &SourceRect,
159 &BlendObj);
160
161 EXLATEOBJ_vCleanup(&exlo);
162 DC_UnlockDc(DCDest);
163 if (hDCSrc != hDCDest)
164 DC_UnlockDc(DCSrc);
165
166 return bResult;
167 }
168
169 BOOL APIENTRY
170 NtGdiBitBlt(
171 HDC hDCDest,
172 INT XDest,
173 INT YDest,
174 INT Width,
175 INT Height,
176 HDC hDCSrc,
177 INT XSrc,
178 INT YSrc,
179 DWORD ROP,
180 IN DWORD crBackColor,
181 IN FLONG fl)
182 {
183 PDC DCDest;
184 PDC DCSrc = NULL;
185 PDC_ATTR pdcattr = NULL;
186 SURFACE *BitmapDest, *BitmapSrc = NULL;
187 RECTL DestRect;
188 POINTL SourcePoint;
189 BOOL Status = FALSE;
190 EXLATEOBJ exlo;
191 XLATEOBJ *XlateObj = NULL;
192 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
193
194 DCDest = DC_LockDc(hDCDest);
195 if (NULL == DCDest)
196 {
197 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
198 return FALSE;
199 }
200
201 if (DCDest->dctype == DC_TYPE_INFO)
202 {
203 DC_UnlockDc(DCDest);
204 /* Yes, Windows really returns TRUE in this case */
205 return TRUE;
206 }
207
208 if (UsesSource)
209 {
210 if (hDCSrc != hDCDest)
211 {
212 DCSrc = DC_LockDc(hDCSrc);
213 if (NULL == DCSrc)
214 {
215 DC_UnlockDc(DCDest);
216 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
217 return FALSE;
218 }
219 if (DCSrc->dctype == DC_TYPE_INFO)
220 {
221 DC_UnlockDc(DCSrc);
222 DC_UnlockDc(DCDest);
223 /* Yes, Windows really returns TRUE in this case */
224 return TRUE;
225 }
226 }
227 else
228 {
229 DCSrc = DCDest;
230 }
231 }
232
233 pdcattr = DCDest->pdcattr;
234
235 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
236 DC_vUpdateFillBrush(DCDest);
237
238 DestRect.left = XDest;
239 DestRect.top = YDest;
240 DestRect.right = XDest+Width;
241 DestRect.bottom = YDest+Height;
242 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
243
244 DestRect.left += DCDest->ptlDCOrig.x;
245 DestRect.top += DCDest->ptlDCOrig.y;
246 DestRect.right += DCDest->ptlDCOrig.x;
247 DestRect.bottom += DCDest->ptlDCOrig.y;
248
249 SourcePoint.x = XSrc;
250 SourcePoint.y = YSrc;
251
252 if (UsesSource)
253 {
254 IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
255
256 SourcePoint.x += DCSrc->ptlDCOrig.x;
257 SourcePoint.y += DCSrc->ptlDCOrig.y;
258 }
259
260 /* Determine surfaces to be used in the bitblt */
261 BitmapDest = DCDest->dclevel.pSurface;
262 if (!BitmapDest)
263 goto cleanup;
264
265 if (UsesSource)
266 {
267 {
268 BitmapSrc = DCSrc->dclevel.pSurface;
269 if (!BitmapSrc)
270 goto cleanup;
271 }
272 }
273
274 /* Create the XLATEOBJ. */
275 if (UsesSource)
276 {
277 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
278 XlateObj = &exlo.xlo;
279 }
280
281 /* Perform the bitblt operation */
282 Status = IntEngBitBlt(&BitmapDest->SurfObj,
283 BitmapSrc ? &BitmapSrc->SurfObj : NULL,
284 NULL,
285 DCDest->rosdc.CombinedClip,
286 XlateObj,
287 &DestRect,
288 &SourcePoint,
289 NULL,
290 &DCDest->eboFill.BrushObject,
291 &DCDest->dclevel.pbrFill->ptOrigin,
292 ROP3_TO_ROP4(ROP));
293
294 cleanup:
295 if (UsesSource)
296 EXLATEOBJ_vCleanup(&exlo);
297 if (UsesSource && hDCSrc != hDCDest)
298 {
299 DC_UnlockDc(DCSrc);
300 }
301 DC_UnlockDc(DCDest);
302
303 return Status;
304 }
305
306 BOOL APIENTRY
307 NtGdiTransparentBlt(
308 HDC hdcDst,
309 INT xDst,
310 INT yDst,
311 INT cxDst,
312 INT cyDst,
313 HDC hdcSrc,
314 INT xSrc,
315 INT ySrc,
316 INT cxSrc,
317 INT cySrc,
318 COLORREF TransColor)
319 {
320 PDC DCDest, DCSrc;
321 RECTL rcDest, rcSrc;
322 SURFACE *BitmapDest, *BitmapSrc = NULL;
323 HPALETTE SourcePalette = 0, DestPalette = 0;
324 PPALETTE PalDestGDI, PalSourceGDI;
325 USHORT PalDestMode, PalSrcMode;
326 ULONG TransparentColor = 0;
327 BOOL Ret = FALSE;
328 EXLATEOBJ exlo;
329
330 if(!(DCDest = DC_LockDc(hdcDst)))
331 {
332 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
333 SetLastWin32Error(ERROR_INVALID_HANDLE);
334 return FALSE;
335 }
336 if (DCDest->dctype == DC_TYPE_INFO)
337 {
338 DC_UnlockDc(DCDest);
339 /* Yes, Windows really returns TRUE in this case */
340 return TRUE;
341 }
342
343 if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
344 {
345 DC_UnlockDc(DCDest);
346 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
347 SetLastWin32Error(ERROR_INVALID_HANDLE);
348 return FALSE;
349 }
350
351 if(hdcDst == hdcSrc)
352 {
353 DCSrc = DCDest;
354 }
355
356 if (DCSrc->dctype == DC_TYPE_INFO)
357 {
358 DC_UnlockDc(DCSrc);
359 if(hdcDst != hdcSrc)
360 {
361 DC_UnlockDc(DCDest);
362 }
363 /* Yes, Windows really returns TRUE in this case */
364 return TRUE;
365 }
366
367 BitmapDest = DCDest->dclevel.pSurface;
368 if (!BitmapDest)
369 {
370 goto done;
371 }
372
373 BitmapSrc = DCSrc->dclevel.pSurface;
374 if (!BitmapSrc)
375 {
376 goto done;
377 }
378
379 DestPalette = BitmapDest->hDIBPalette;
380 if (!DestPalette) DestPalette = pPrimarySurface->devinfo.hpalDefault;
381
382 SourcePalette = BitmapSrc->hDIBPalette;
383 if (!SourcePalette) SourcePalette = pPrimarySurface->devinfo.hpalDefault;
384
385 if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
386 {
387 SetLastWin32Error(ERROR_INVALID_HANDLE);
388 goto done;
389 }
390 PalSrcMode = PalSourceGDI->Mode;
391 PALETTE_UnlockPalette(PalSourceGDI);
392
393 if(DestPalette != SourcePalette)
394 {
395 if (!(PalDestGDI = PALETTE_LockPalette(DestPalette)))
396 {
397 SetLastWin32Error(ERROR_INVALID_HANDLE);
398 goto done;
399 }
400 PalDestMode = PalDestGDI->Mode;
401 PALETTE_UnlockPalette(PalDestGDI);
402 }
403 else
404 {
405 PalDestMode = PalSrcMode;
406 PalDestGDI = PalSourceGDI;
407 }
408
409 /* Translate Transparent (RGB) Color to the source palette */
410 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalSourceGDI, 0, 0, 0);
411 TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
412 EXLATEOBJ_vCleanup(&exlo);
413
414 EXLATEOBJ_vInitialize(&exlo, PalSourceGDI, PalDestGDI, 0, 0, 0);
415
416 rcDest.left = xDst;
417 rcDest.top = yDst;
418 rcDest.right = rcDest.left + cxDst;
419 rcDest.bottom = rcDest.top + cyDst;
420 IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
421
422 rcDest.left += DCDest->ptlDCOrig.x;
423 rcDest.top += DCDest->ptlDCOrig.y;
424 rcDest.right += DCDest->ptlDCOrig.x;
425 rcDest.bottom += DCDest->ptlDCOrig.y;
426
427 rcSrc.left = xSrc;
428 rcSrc.top = ySrc;
429 rcSrc.right = rcSrc.left + cxSrc;
430 rcSrc.bottom = rcSrc.top + cySrc;
431 IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
432
433 rcSrc.left += DCSrc->ptlDCOrig.x;
434 rcSrc.top += DCSrc->ptlDCOrig.y;
435 rcSrc.right += DCSrc->ptlDCOrig.x;
436 rcSrc.bottom += DCSrc->ptlDCOrig.y;
437
438 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
439 DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
440 TransparentColor, 0);
441
442 done:
443 DC_UnlockDc(DCSrc);
444 if(hdcDst != hdcSrc)
445 {
446 DC_UnlockDc(DCDest);
447 }
448 EXLATEOBJ_vCleanup(&exlo);
449 return Ret;
450 }
451
452 /***********************************************************************
453 * MaskBlt
454 * Ported from WINE by sedwards 11-4-03
455 *
456 * Someone thought it would be faster to do it here and then switch back
457 * to GDI32. I dunno. Write a test and let me know.
458 * A. It should be in here!
459 */
460
461 static __inline BYTE
462 SwapROP3_SrcDst(BYTE bRop3)
463 {
464 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
465 }
466
467 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
468 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
469 #define DSTCOPY 0x00AA0029
470 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
471
472 BOOL APIENTRY
473 NtGdiMaskBlt(
474 HDC hdcDest,
475 INT nXDest,
476 INT nYDest,
477 INT nWidth,
478 INT nHeight,
479 HDC hdcSrc,
480 INT nXSrc,
481 INT nYSrc,
482 HBITMAP hbmMask,
483 INT xMask,
484 INT yMask,
485 DWORD dwRop,
486 IN DWORD crBackColor)
487 {
488 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
489 HDC hDCMask, hDC1, hDC2;
490 static const DWORD ROP3Table[256] =
491 {
492 0x00000042, 0x00010289,
493 0x00020C89, 0x000300AA,
494 0x00040C88, 0x000500A9,
495 0x00060865, 0x000702C5,
496 0x00080F08, 0x00090245,
497 0x000A0329, 0x000B0B2A,
498 0x000C0324, 0x000D0B25,
499 0x000E08A5, 0x000F0001,
500 0x00100C85, 0x001100A6,
501 0x00120868, 0x001302C8,
502 0x00140869, 0x001502C9,
503 0x00165CCA, 0x00171D54,
504 0x00180D59, 0x00191CC8,
505 0x001A06C5, 0x001B0768,
506 0x001C06CA, 0x001D0766,
507 0x001E01A5, 0x001F0385,
508 0x00200F09, 0x00210248,
509 0x00220326, 0x00230B24,
510 0x00240D55, 0x00251CC5,
511 0x002606C8, 0x00271868,
512 0x00280369, 0x002916CA,
513 0x002A0CC9, 0x002B1D58,
514 0x002C0784, 0x002D060A,
515 0x002E064A, 0x002F0E2A,
516 0x0030032A, 0x00310B28,
517 0x00320688, 0x00330008,
518 0x003406C4, 0x00351864,
519 0x003601A8, 0x00370388,
520 0x0038078A, 0x00390604,
521 0x003A0644, 0x003B0E24,
522 0x003C004A, 0x003D18A4,
523 0x003E1B24, 0x003F00EA,
524 0x00400F0A, 0x00410249,
525 0x00420D5D, 0x00431CC4,
526 0x00440328, 0x00450B29,
527 0x004606C6, 0x0047076A,
528 0x00480368, 0x004916C5,
529 0x004A0789, 0x004B0605,
530 0x004C0CC8, 0x004D1954,
531 0x004E0645, 0x004F0E25,
532 0x00500325, 0x00510B26,
533 0x005206C9, 0x00530764,
534 0x005408A9, 0x00550009,
535 0x005601A9, 0x00570389,
536 0x00580785, 0x00590609,
537 0x005A0049, 0x005B18A9,
538 0x005C0649, 0x005D0E29,
539 0x005E1B29, 0x005F00E9,
540 0x00600365, 0x006116C6,
541 0x00620786, 0x00630608,
542 0x00640788, 0x00650606,
543 0x00660046, 0x006718A8,
544 0x006858A6, 0x00690145,
545 0x006A01E9, 0x006B178A,
546 0x006C01E8, 0x006D1785,
547 0x006E1E28, 0x006F0C65,
548 0x00700CC5, 0x00711D5C,
549 0x00720648, 0x00730E28,
550 0x00740646, 0x00750E26,
551 0x00761B28, 0x007700E6,
552 0x007801E5, 0x00791786,
553 0x007A1E29, 0x007B0C68,
554 0x007C1E24, 0x007D0C69,
555 0x007E0955, 0x007F03C9,
556 0x008003E9, 0x00810975,
557 0x00820C49, 0x00831E04,
558 0x00840C48, 0x00851E05,
559 0x008617A6, 0x008701C5,
560 0x008800C6, 0x00891B08,
561 0x008A0E06, 0x008B0666,
562 0x008C0E08, 0x008D0668,
563 0x008E1D7C, 0x008F0CE5,
564 0x00900C45, 0x00911E08,
565 0x009217A9, 0x009301C4,
566 0x009417AA, 0x009501C9,
567 0x00960169, 0x0097588A,
568 0x00981888, 0x00990066,
569 0x009A0709, 0x009B07A8,
570 0x009C0704, 0x009D07A6,
571 0x009E16E6, 0x009F0345,
572 0x00A000C9, 0x00A11B05,
573 0x00A20E09, 0x00A30669,
574 0x00A41885, 0x00A50065,
575 0x00A60706, 0x00A707A5,
576 0x00A803A9, 0x00A90189,
577 0x00AA0029, 0x00AB0889,
578 0x00AC0744, 0x00AD06E9,
579 0x00AE0B06, 0x00AF0229,
580 0x00B00E05, 0x00B10665,
581 0x00B21974, 0x00B30CE8,
582 0x00B4070A, 0x00B507A9,
583 0x00B616E9, 0x00B70348,
584 0x00B8074A, 0x00B906E6,
585 0x00BA0B09, 0x00BB0226,
586 0x00BC1CE4, 0x00BD0D7D,
587 0x00BE0269, 0x00BF08C9,
588 0x00C000CA, 0x00C11B04,
589 0x00C21884, 0x00C3006A,
590 0x00C40E04, 0x00C50664,
591 0x00C60708, 0x00C707AA,
592 0x00C803A8, 0x00C90184,
593 0x00CA0749, 0x00CB06E4,
594 0x00CC0020, 0x00CD0888,
595 0x00CE0B08, 0x00CF0224,
596 0x00D00E0A, 0x00D1066A,
597 0x00D20705, 0x00D307A4,
598 0x00D41D78, 0x00D50CE9,
599 0x00D616EA, 0x00D70349,
600 0x00D80745, 0x00D906E8,
601 0x00DA1CE9, 0x00DB0D75,
602 0x00DC0B04, 0x00DD0228,
603 0x00DE0268, 0x00DF08C8,
604 0x00E003A5, 0x00E10185,
605 0x00E20746, 0x00E306EA,
606 0x00E40748, 0x00E506E5,
607 0x00E61CE8, 0x00E70D79,
608 0x00E81D74, 0x00E95CE6,
609 0x00EA02E9, 0x00EB0849,
610 0x00EC02E8, 0x00ED0848,
611 0x00EE0086, 0x00EF0A08,
612 0x00F00021, 0x00F10885,
613 0x00F20B05, 0x00F3022A,
614 0x00F40B0A, 0x00F50225,
615 0x00F60265, 0x00F708C5,
616 0x00F802E5, 0x00F90845,
617 0x00FA0089, 0x00FB0A09,
618 0x00FC008A, 0x00FD0A0A,
619 0x00FE02A9, 0x00FF0062,
620 };
621
622 if (!hbmMask)
623 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0);
624
625 /* 1. make mask bitmap's dc */
626 hDCMask = NtGdiCreateCompatibleDC(hdcDest);
627 hOldMaskBitmap = (HBITMAP)NtGdiSelectBitmap(hDCMask, hbmMask);
628
629 /* 2. make masked Background bitmap */
630
631 /* 2.1 make bitmap */
632 hDC1 = NtGdiCreateCompatibleDC(hdcDest);
633 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
634 hOldBitmap2 = (HBITMAP)NtGdiSelectBitmap(hDC1, hBitmap2);
635
636 /* 2.2 draw dest bitmap and mask */
637 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
638 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
639 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE, 0, 0);
640
641 /* 3. make masked Foreground bitmap */
642
643 /* 3.1 make bitmap */
644 hDC2 = NtGdiCreateCompatibleDC(hdcDest);
645 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
646 hOldBitmap3 = (HBITMAP)NtGdiSelectBitmap(hDC2, hBitmap3);
647
648 /* 3.2 draw src bitmap and mask */
649 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
650 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
651 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND, 0, 0);
652
653 /* 4. combine both and copy the result to hdcDest */
654 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT, 0, 0);
655 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY, 0, 0);
656
657 /* 5. restore all objects */
658 NtGdiSelectBitmap(hDCMask, hOldMaskBitmap);
659 NtGdiSelectBitmap(hDC1, hOldBitmap2);
660 NtGdiSelectBitmap(hDC2, hOldBitmap3);
661
662 /* 6. delete all temp objects */
663 GreDeleteObject(hBitmap2);
664 GreDeleteObject(hBitmap3);
665
666 NtGdiDeleteObjectApp(hDC1);
667 NtGdiDeleteObjectApp(hDC2);
668 NtGdiDeleteObjectApp(hDCMask);
669
670 return TRUE;
671 }
672
673 BOOL
674 APIENTRY
675 NtGdiPlgBlt(
676 IN HDC hdcTrg,
677 IN LPPOINT pptlTrg,
678 IN HDC hdcSrc,
679 IN INT xSrc,
680 IN INT ySrc,
681 IN INT cxSrc,
682 IN INT cySrc,
683 IN HBITMAP hbmMask,
684 IN INT xMask,
685 IN INT yMask,
686 IN DWORD crBackColor)
687 {
688 UNIMPLEMENTED;
689 return FALSE;
690 }
691
692 BOOL APIENTRY
693 GreStretchBltMask(
694 HDC hDCDest,
695 INT XOriginDest,
696 INT YOriginDest,
697 INT WidthDest,
698 INT HeightDest,
699 HDC hDCSrc,
700 INT XOriginSrc,
701 INT YOriginSrc,
702 INT WidthSrc,
703 INT HeightSrc,
704 DWORD ROP,
705 IN DWORD dwBackColor,
706 HDC hDCMask)
707 {
708 PDC DCDest;
709 PDC DCSrc = NULL;
710 PDC DCMask = NULL;
711 PDC_ATTR pdcattr;
712 SURFACE *BitmapDest, *BitmapSrc = NULL;
713 SURFACE *BitmapMask = NULL;
714 RECTL DestRect;
715 RECTL SourceRect;
716 BOOL Status = FALSE;
717 EXLATEOBJ exlo;
718 XLATEOBJ *XlateObj = NULL;
719 POINTL BrushOrigin;
720 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
721
722 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
723 {
724 SetLastWin32Error(ERROR_INVALID_PARAMETER);
725 return FALSE;
726 }
727
728 DCDest = DC_LockDc(hDCDest);
729 if (NULL == DCDest)
730 {
731 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
732 SetLastWin32Error(ERROR_INVALID_HANDLE);
733 return FALSE;
734 }
735
736 if (DCDest->dctype == DC_TYPE_INFO)
737 {
738 DC_UnlockDc(DCDest);
739 /* Yes, Windows really returns TRUE in this case */
740 return TRUE;
741 }
742
743 if (UsesSource)
744 {
745 if (hDCSrc != hDCDest)
746 {
747 DCSrc = DC_LockDc(hDCSrc);
748 if (NULL == DCSrc)
749 {
750 DC_UnlockDc(DCDest);
751 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
752 SetLastWin32Error(ERROR_INVALID_HANDLE);
753 return FALSE;
754 }
755 if (DCSrc->dctype == DC_TYPE_INFO)
756 {
757 DC_UnlockDc(DCSrc);
758 DC_UnlockDc(DCDest);
759 /* Yes, Windows really returns TRUE in this case */
760 return TRUE;
761 }
762 }
763 else
764 {
765 DCSrc = DCDest;
766 }
767 }
768
769 pdcattr = DCDest->pdcattr;
770
771 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
772 DC_vUpdateFillBrush(DCDest);
773
774 DestRect.left = XOriginDest;
775 DestRect.top = YOriginDest;
776 DestRect.right = XOriginDest+WidthDest;
777 DestRect.bottom = YOriginDest+HeightDest;
778 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
779
780 DestRect.left += DCDest->ptlDCOrig.x;
781 DestRect.top += DCDest->ptlDCOrig.y;
782 DestRect.right += DCDest->ptlDCOrig.x;
783 DestRect.bottom += DCDest->ptlDCOrig.y;
784
785 SourceRect.left = XOriginSrc;
786 SourceRect.top = YOriginSrc;
787 SourceRect.right = XOriginSrc+WidthSrc;
788 SourceRect.bottom = YOriginSrc+HeightSrc;
789
790 if (UsesSource)
791 {
792 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
793
794 SourceRect.left += DCSrc->ptlDCOrig.x;
795 SourceRect.top += DCSrc->ptlDCOrig.y;
796 SourceRect.right += DCSrc->ptlDCOrig.x;
797 SourceRect.bottom += DCSrc->ptlDCOrig.y;
798 }
799
800 BrushOrigin.x = 0;
801 BrushOrigin.y = 0;
802
803 /* Determine surfaces to be used in the bitblt */
804 BitmapDest = DCDest->dclevel.pSurface;
805 if (BitmapDest == NULL)
806 goto failed;
807 if (UsesSource)
808 {
809 BitmapSrc = DCSrc->dclevel.pSurface;
810 if (BitmapSrc == NULL)
811 goto failed;
812
813 /* Create the XLATEOBJ. */
814 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
815 XlateObj = &exlo.xlo;
816 }
817
818 /* Offset the brush */
819 BrushOrigin.x += DCDest->ptlDCOrig.x;
820 BrushOrigin.y += DCDest->ptlDCOrig.y;
821
822 /* Make mask surface for source surface */
823 if (BitmapSrc && hDCMask)
824 {
825 DCMask = DC_LockDc(hDCMask);
826 if (DCMask)
827 {
828 BitmapMask = DCMask->dclevel.pSurface;
829 if (BitmapMask &&
830 (BitmapMask->SurfObj.sizlBitmap.cx != WidthSrc ||
831 BitmapMask->SurfObj.sizlBitmap.cy != HeightSrc))
832 {
833 DPRINT1("Mask and bitmap sizes don't match!\n");
834 goto failed;
835 }
836 }
837 }
838
839 /* Perform the bitblt operation */
840 Status = IntEngStretchBlt(&BitmapDest->SurfObj,
841 &BitmapSrc->SurfObj,
842 BitmapMask ? &BitmapMask->SurfObj : NULL,
843 DCDest->rosdc.CombinedClip,
844 XlateObj,
845 &DestRect,
846 &SourceRect,
847 NULL,
848 &DCDest->eboFill.BrushObject,
849 &BrushOrigin,
850 ROP3_TO_ROP4(ROP));
851
852 failed:
853 if (UsesSource)
854 {
855 EXLATEOBJ_vCleanup(&exlo);
856 }
857 if (UsesSource && hDCSrc != hDCDest)
858 {
859 DC_UnlockDc(DCSrc);
860 }
861 if (DCMask)
862 {
863 DC_UnlockDc(DCMask);
864 }
865 DC_UnlockDc(DCDest);
866
867 return Status;
868 }
869
870
871 BOOL APIENTRY
872 NtGdiStretchBlt(
873 HDC hDCDest,
874 INT XOriginDest,
875 INT YOriginDest,
876 INT WidthDest,
877 INT HeightDest,
878 HDC hDCSrc,
879 INT XOriginSrc,
880 INT YOriginSrc,
881 INT WidthSrc,
882 INT HeightSrc,
883 DWORD ROP,
884 IN DWORD dwBackColor)
885 {
886 return GreStretchBltMask(
887 hDCDest,
888 XOriginDest,
889 YOriginDest,
890 WidthDest,
891 HeightDest,
892 hDCSrc,
893 XOriginSrc,
894 YOriginSrc,
895 WidthSrc,
896 HeightSrc,
897 ROP,
898 dwBackColor,
899 NULL);
900 }
901
902
903 BOOL FASTCALL
904 IntPatBlt(
905 PDC pdc,
906 INT XLeft,
907 INT YLeft,
908 INT Width,
909 INT Height,
910 DWORD dwRop,
911 PBRUSH pbrush)
912 {
913 RECTL DestRect;
914 SURFACE *psurf;
915 EBRUSHOBJ eboFill;
916 POINTL BrushOrigin;
917 BOOL ret;
918
919 ASSERT(pbrush);
920
921 psurf = pdc->dclevel.pSurface;
922 if (psurf == NULL)
923 {
924 SetLastWin32Error(ERROR_INVALID_HANDLE);
925 return FALSE;
926 }
927
928 if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
929 {
930 return TRUE;
931 }
932
933 if (Width > 0)
934 {
935 DestRect.left = XLeft;
936 DestRect.right = XLeft + Width;
937 }
938 else
939 {
940 DestRect.left = XLeft + Width + 1;
941 DestRect.right = XLeft + 1;
942 }
943
944 if (Height > 0)
945 {
946 DestRect.top = YLeft;
947 DestRect.bottom = YLeft + Height;
948 }
949 else
950 {
951 DestRect.top = YLeft + Height + 1;
952 DestRect.bottom = YLeft + 1;
953 }
954
955 IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
956
957 DestRect.left += pdc->ptlDCOrig.x;
958 DestRect.top += pdc->ptlDCOrig.y;
959 DestRect.right += pdc->ptlDCOrig.x;
960 DestRect.bottom += pdc->ptlDCOrig.y;
961
962 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
963 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
964
965 EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
966
967 ret = IntEngBitBlt(
968 &psurf->SurfObj,
969 NULL,
970 NULL,
971 pdc->rosdc.CombinedClip,
972 NULL,
973 &DestRect,
974 NULL,
975 NULL,
976 &eboFill.BrushObject, // use pDC->eboFill
977 &BrushOrigin,
978 ROP3_TO_ROP4(dwRop));
979
980 EBRUSHOBJ_vCleanup(&eboFill);
981
982 return ret;
983 }
984
985 BOOL FASTCALL
986 IntGdiPolyPatBlt(
987 HDC hDC,
988 DWORD dwRop,
989 PPATRECT pRects,
990 INT cRects,
991 ULONG Reserved)
992 {
993 INT i;
994 PBRUSH pbrush;
995 PDC pdc;
996
997 pdc = DC_LockDc(hDC);
998 if (!pdc)
999 {
1000 SetLastWin32Error(ERROR_INVALID_HANDLE);
1001 return FALSE;
1002 }
1003
1004 if (pdc->dctype == DC_TYPE_INFO)
1005 {
1006 DC_UnlockDc(pdc);
1007 /* Yes, Windows really returns TRUE in this case */
1008 return TRUE;
1009 }
1010
1011 for (i = 0; i < cRects; i++)
1012 {
1013 pbrush = BRUSH_LockBrush(pRects->hBrush);
1014 if(pbrush != NULL)
1015 {
1016 IntPatBlt(
1017 pdc,
1018 pRects->r.left,
1019 pRects->r.top,
1020 pRects->r.right,
1021 pRects->r.bottom,
1022 dwRop,
1023 pbrush);
1024 BRUSH_UnlockBrush(pbrush);
1025 }
1026 pRects++;
1027 }
1028
1029 DC_UnlockDc(pdc);
1030
1031 return TRUE;
1032 }
1033
1034
1035 BOOL APIENTRY
1036 NtGdiPatBlt(
1037 HDC hDC,
1038 INT XLeft,
1039 INT YLeft,
1040 INT Width,
1041 INT Height,
1042 DWORD ROP)
1043 {
1044 PBRUSH pbrush;
1045 DC *dc;
1046 PDC_ATTR pdcattr;
1047 BOOL ret;
1048
1049 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
1050 if (UsesSource)
1051 {
1052 /* in this case we call on GdiMaskBlt */
1053 return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0);
1054 }
1055
1056 dc = DC_LockDc(hDC);
1057 if (dc == NULL)
1058 {
1059 SetLastWin32Error(ERROR_INVALID_HANDLE);
1060 return FALSE;
1061 }
1062 if (dc->dctype == DC_TYPE_INFO)
1063 {
1064 DC_UnlockDc(dc);
1065 /* Yes, Windows really returns TRUE in this case */
1066 return TRUE;
1067 }
1068
1069 pdcattr = dc->pdcattr;
1070
1071 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
1072 DC_vUpdateFillBrush(dc);
1073
1074 pbrush = BRUSH_LockBrush(pdcattr->hbrush);
1075 if (pbrush == NULL)
1076 {
1077 SetLastWin32Error(ERROR_INVALID_HANDLE);
1078 DC_UnlockDc(dc);
1079 return FALSE;
1080 }
1081
1082 ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush);
1083
1084 BRUSH_UnlockBrush(pbrush);
1085 DC_UnlockDc(dc);
1086
1087 return ret;
1088 }
1089
1090 BOOL APIENTRY
1091 NtGdiPolyPatBlt(
1092 HDC hDC,
1093 DWORD dwRop,
1094 IN PPOLYPATBLT pRects,
1095 IN DWORD cRects,
1096 IN DWORD Mode)
1097 {
1098 PPATRECT rb = NULL;
1099 NTSTATUS Status = STATUS_SUCCESS;
1100 BOOL Ret;
1101
1102 if (cRects > 0)
1103 {
1104 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
1105 if (!rb)
1106 {
1107 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1108 return FALSE;
1109 }
1110 _SEH2_TRY
1111 {
1112 ProbeForRead(pRects,
1113 cRects * sizeof(PATRECT),
1114 1);
1115 RtlCopyMemory(rb,
1116 pRects,
1117 cRects * sizeof(PATRECT));
1118 }
1119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1120 {
1121 Status = _SEH2_GetExceptionCode();
1122 }
1123 _SEH2_END;
1124
1125 if (!NT_SUCCESS(Status))
1126 {
1127 ExFreePoolWithTag(rb, TAG_PATBLT);
1128 SetLastNtError(Status);
1129 return FALSE;
1130 }
1131 }
1132
1133 Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
1134
1135 if (cRects > 0)
1136 ExFreePoolWithTag(rb, TAG_PATBLT);
1137
1138 return Ret;
1139 }