2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
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.
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.
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.
19 /* $Id: bitmaps.c 28300 2007-08-12 15:20:09Z tkreuzer $ */
40 BLENDFUNCTION BlendFunc
,
47 SURFACE
*BitmapDest
, *BitmapSrc
;
48 RECTL DestRect
, SourceRect
;
52 BlendObj
.BlendFunction
= BlendFunc
;
54 if (WidthDest
< 0 || HeightDest
< 0 || WidthSrc
< 0 || HeightSrc
< 0)
56 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
60 DPRINT("Locking DCs\n");
63 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
67 if ((NULL
== DCDest
) || (NULL
== DCSrc
))
69 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
, hDCSrc
);
70 SetLastWin32Error(ERROR_INVALID_HANDLE
);
71 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
72 if(DCDest
) GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
76 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
78 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
79 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
80 /* Yes, Windows really returns TRUE in this case */
84 DestRect
.left
= XOriginDest
;
85 DestRect
.top
= YOriginDest
;
86 DestRect
.right
= XOriginDest
+ WidthDest
;
87 DestRect
.bottom
= YOriginDest
+ HeightDest
;
88 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
90 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
91 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
92 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
93 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
95 SourceRect
.left
= XOriginSrc
;
96 SourceRect
.top
= YOriginSrc
;
97 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
98 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
99 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
101 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
102 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
103 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
104 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
106 if (!DestRect
.right
||
111 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
112 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
116 /* Prepare DCs for blit */
117 DPRINT("Preparing DCs for blit\n");
118 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
120 /* Determine surfaces to be used in the bitblt */
121 BitmapDest
= DCDest
->dclevel
.pSurface
;
128 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
135 /* Create the XLATEOBJ. */
136 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
138 /* Perform the alpha blend operation */
139 DPRINT("Performing the alpha Blend\n");
140 bResult
= IntEngAlphaBlend(&BitmapDest
->SurfObj
,
142 DCDest
->rosdc
.CombinedClip
,
148 EXLATEOBJ_vCleanup(&exlo
);
150 DPRINT("Finishing blit\n");
151 DC_vFinishBlit(DCDest
, DCSrc
);
152 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
153 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
169 IN DWORD crBackColor
,
176 PDC_ATTR pdcattr
= NULL
;
177 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
178 RECTL DestRect
, SourceRect
;
182 XLATEOBJ
*XlateObj
= NULL
;
183 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
185 DPRINT("Locking DCs\n");
188 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
194 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
195 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
199 if (DCDest
->dctype
== DC_TYPE_INFO
)
201 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
202 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
203 /* Yes, Windows really returns TRUE in this case */
211 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
212 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
215 if (DCSrc
->dctype
== DC_TYPE_INFO
)
217 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
218 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
219 /* Yes, Windows really returns TRUE in this case */
225 DPRINT1("Getting a valid Source handle without using source!!!");
226 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
230 pdcattr
= DCDest
->pdcattr
;
232 DestRect
.left
= XDest
;
233 DestRect
.top
= YDest
;
234 DestRect
.right
= XDest
+Width
;
235 DestRect
.bottom
= YDest
+Height
;
236 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
238 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
239 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
240 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
241 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
243 SourcePoint
.x
= XSrc
;
244 SourcePoint
.y
= YSrc
;
248 IntLPtoDP(DCSrc
, (LPPOINT
)&SourcePoint
, 1);
250 SourcePoint
.x
+= DCSrc
->ptlDCOrig
.x
;
251 SourcePoint
.y
+= DCSrc
->ptlDCOrig
.y
;
252 /* Calculate Source Rect */
253 SourceRect
.left
= SourcePoint
.x
;
254 SourceRect
.top
= SourcePoint
.y
;
255 SourceRect
.right
= SourcePoint
.x
+ DestRect
.right
- DestRect
.left
;
256 SourceRect
.bottom
= SourcePoint
.y
+ DestRect
.bottom
- DestRect
.top
;
260 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
262 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
263 DC_vUpdateFillBrush(DCDest
);
265 /* Determine surfaces to be used in the bitblt */
266 BitmapDest
= DCDest
->dclevel
.pSurface
;
273 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
279 /* Create the XLATEOBJ. */
282 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
283 XlateObj
= &exlo
.xlo
;
286 /* Perform the bitblt operation */
287 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
,
288 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
290 DCDest
->rosdc
.CombinedClip
,
295 &DCDest
->eboFill
.BrushObject
,
296 &DCDest
->dclevel
.pbrFill
->ptOrigin
,
300 EXLATEOBJ_vCleanup(&exlo
);
302 DC_vFinishBlit(DCDest
, DCSrc
);
305 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
307 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
330 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
331 HPALETTE SourcePalette
= 0, DestPalette
= 0;
332 PPALETTE PalDestGDI
, PalSourceGDI
;
333 USHORT PalDestMode
, PalSrcMode
;
334 ULONG TransparentColor
= 0;
338 DPRINT("Locking DCs\n");
341 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
345 if ((NULL
== DCDest
) || (NULL
== DCSrc
))
347 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst
, hdcSrc
);
348 SetLastWin32Error(ERROR_INVALID_HANDLE
);
349 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
350 if(DCDest
) GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
354 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
356 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
357 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
358 /* Yes, Windows really returns TRUE in this case */
364 rcDest
.right
= rcDest
.left
+ cxDst
;
365 rcDest
.bottom
= rcDest
.top
+ cyDst
;
366 IntLPtoDP(DCDest
, (LPPOINT
)&rcDest
, 2);
368 rcDest
.left
+= DCDest
->ptlDCOrig
.x
;
369 rcDest
.top
+= DCDest
->ptlDCOrig
.y
;
370 rcDest
.right
+= DCDest
->ptlDCOrig
.x
;
371 rcDest
.bottom
+= DCDest
->ptlDCOrig
.y
;
375 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
376 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
377 IntLPtoDP(DCSrc
, (LPPOINT
)&rcSrc
, 2);
379 rcSrc
.left
+= DCSrc
->ptlDCOrig
.x
;
380 rcSrc
.top
+= DCSrc
->ptlDCOrig
.y
;
381 rcSrc
.right
+= DCSrc
->ptlDCOrig
.x
;
382 rcSrc
.bottom
+= DCSrc
->ptlDCOrig
.y
;
384 /* Prepare for blit */
385 DC_vPrepareDCsForBlit(DCDest
, rcDest
, DCSrc
, rcSrc
);
387 BitmapDest
= DCDest
->dclevel
.pSurface
;
393 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
399 DestPalette
= BitmapDest
->hDIBPalette
;
400 if (!DestPalette
) DestPalette
= pPrimarySurface
->devinfo
.hpalDefault
;
402 SourcePalette
= BitmapSrc
->hDIBPalette
;
403 if (!SourcePalette
) SourcePalette
= pPrimarySurface
->devinfo
.hpalDefault
;
405 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
407 SetLastWin32Error(ERROR_INVALID_HANDLE
);
410 PalSrcMode
= PalSourceGDI
->Mode
;
411 PALETTE_UnlockPalette(PalSourceGDI
);
413 if(DestPalette
!= SourcePalette
)
415 if (!(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
417 SetLastWin32Error(ERROR_INVALID_HANDLE
);
420 PalDestMode
= PalDestGDI
->Mode
;
421 PALETTE_UnlockPalette(PalDestGDI
);
425 PalDestMode
= PalSrcMode
;
426 PalDestGDI
= PalSourceGDI
;
429 /* Translate Transparent (RGB) Color to the source palette */
430 EXLATEOBJ_vInitialize(&exlo
, &gpalRGB
, PalSourceGDI
, 0, 0, 0);
431 TransparentColor
= XLATEOBJ_iXlate(&exlo
.xlo
, (ULONG
)TransColor
);
432 EXLATEOBJ_vCleanup(&exlo
);
434 EXLATEOBJ_vInitialize(&exlo
, PalSourceGDI
, PalDestGDI
, 0, 0, 0);
436 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
437 DCDest
->rosdc
.CombinedClip
, &exlo
.xlo
, &rcDest
, &rcSrc
,
438 TransparentColor
, 0);
440 EXLATEOBJ_vCleanup(&exlo
);
443 DC_vFinishBlit(DCDest
, DCSrc
);
444 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
445 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
450 /***********************************************************************
452 * Ported from WINE by sedwards 11-4-03
454 * Someone thought it would be faster to do it here and then switch back
455 * to GDI32. I dunno. Write a test and let me know.
456 * A. It should be in here!
460 SwapROP3_SrcDst(BYTE bRop3
)
462 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
465 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
466 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
467 #define DSTCOPY 0x00AA0029
468 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
484 IN DWORD crBackColor
)
486 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
487 HDC hDCMask
, hDC1
, hDC2
;
488 static const DWORD ROP3Table
[256] =
490 0x00000042, 0x00010289,
491 0x00020C89, 0x000300AA,
492 0x00040C88, 0x000500A9,
493 0x00060865, 0x000702C5,
494 0x00080F08, 0x00090245,
495 0x000A0329, 0x000B0B2A,
496 0x000C0324, 0x000D0B25,
497 0x000E08A5, 0x000F0001,
498 0x00100C85, 0x001100A6,
499 0x00120868, 0x001302C8,
500 0x00140869, 0x001502C9,
501 0x00165CCA, 0x00171D54,
502 0x00180D59, 0x00191CC8,
503 0x001A06C5, 0x001B0768,
504 0x001C06CA, 0x001D0766,
505 0x001E01A5, 0x001F0385,
506 0x00200F09, 0x00210248,
507 0x00220326, 0x00230B24,
508 0x00240D55, 0x00251CC5,
509 0x002606C8, 0x00271868,
510 0x00280369, 0x002916CA,
511 0x002A0CC9, 0x002B1D58,
512 0x002C0784, 0x002D060A,
513 0x002E064A, 0x002F0E2A,
514 0x0030032A, 0x00310B28,
515 0x00320688, 0x00330008,
516 0x003406C4, 0x00351864,
517 0x003601A8, 0x00370388,
518 0x0038078A, 0x00390604,
519 0x003A0644, 0x003B0E24,
520 0x003C004A, 0x003D18A4,
521 0x003E1B24, 0x003F00EA,
522 0x00400F0A, 0x00410249,
523 0x00420D5D, 0x00431CC4,
524 0x00440328, 0x00450B29,
525 0x004606C6, 0x0047076A,
526 0x00480368, 0x004916C5,
527 0x004A0789, 0x004B0605,
528 0x004C0CC8, 0x004D1954,
529 0x004E0645, 0x004F0E25,
530 0x00500325, 0x00510B26,
531 0x005206C9, 0x00530764,
532 0x005408A9, 0x00550009,
533 0x005601A9, 0x00570389,
534 0x00580785, 0x00590609,
535 0x005A0049, 0x005B18A9,
536 0x005C0649, 0x005D0E29,
537 0x005E1B29, 0x005F00E9,
538 0x00600365, 0x006116C6,
539 0x00620786, 0x00630608,
540 0x00640788, 0x00650606,
541 0x00660046, 0x006718A8,
542 0x006858A6, 0x00690145,
543 0x006A01E9, 0x006B178A,
544 0x006C01E8, 0x006D1785,
545 0x006E1E28, 0x006F0C65,
546 0x00700CC5, 0x00711D5C,
547 0x00720648, 0x00730E28,
548 0x00740646, 0x00750E26,
549 0x00761B28, 0x007700E6,
550 0x007801E5, 0x00791786,
551 0x007A1E29, 0x007B0C68,
552 0x007C1E24, 0x007D0C69,
553 0x007E0955, 0x007F03C9,
554 0x008003E9, 0x00810975,
555 0x00820C49, 0x00831E04,
556 0x00840C48, 0x00851E05,
557 0x008617A6, 0x008701C5,
558 0x008800C6, 0x00891B08,
559 0x008A0E06, 0x008B0666,
560 0x008C0E08, 0x008D0668,
561 0x008E1D7C, 0x008F0CE5,
562 0x00900C45, 0x00911E08,
563 0x009217A9, 0x009301C4,
564 0x009417AA, 0x009501C9,
565 0x00960169, 0x0097588A,
566 0x00981888, 0x00990066,
567 0x009A0709, 0x009B07A8,
568 0x009C0704, 0x009D07A6,
569 0x009E16E6, 0x009F0345,
570 0x00A000C9, 0x00A11B05,
571 0x00A20E09, 0x00A30669,
572 0x00A41885, 0x00A50065,
573 0x00A60706, 0x00A707A5,
574 0x00A803A9, 0x00A90189,
575 0x00AA0029, 0x00AB0889,
576 0x00AC0744, 0x00AD06E9,
577 0x00AE0B06, 0x00AF0229,
578 0x00B00E05, 0x00B10665,
579 0x00B21974, 0x00B30CE8,
580 0x00B4070A, 0x00B507A9,
581 0x00B616E9, 0x00B70348,
582 0x00B8074A, 0x00B906E6,
583 0x00BA0B09, 0x00BB0226,
584 0x00BC1CE4, 0x00BD0D7D,
585 0x00BE0269, 0x00BF08C9,
586 0x00C000CA, 0x00C11B04,
587 0x00C21884, 0x00C3006A,
588 0x00C40E04, 0x00C50664,
589 0x00C60708, 0x00C707AA,
590 0x00C803A8, 0x00C90184,
591 0x00CA0749, 0x00CB06E4,
592 0x00CC0020, 0x00CD0888,
593 0x00CE0B08, 0x00CF0224,
594 0x00D00E0A, 0x00D1066A,
595 0x00D20705, 0x00D307A4,
596 0x00D41D78, 0x00D50CE9,
597 0x00D616EA, 0x00D70349,
598 0x00D80745, 0x00D906E8,
599 0x00DA1CE9, 0x00DB0D75,
600 0x00DC0B04, 0x00DD0228,
601 0x00DE0268, 0x00DF08C8,
602 0x00E003A5, 0x00E10185,
603 0x00E20746, 0x00E306EA,
604 0x00E40748, 0x00E506E5,
605 0x00E61CE8, 0x00E70D79,
606 0x00E81D74, 0x00E95CE6,
607 0x00EA02E9, 0x00EB0849,
608 0x00EC02E8, 0x00ED0848,
609 0x00EE0086, 0x00EF0A08,
610 0x00F00021, 0x00F10885,
611 0x00F20B05, 0x00F3022A,
612 0x00F40B0A, 0x00F50225,
613 0x00F60265, 0x00F708C5,
614 0x00F802E5, 0x00F90845,
615 0x00FA0089, 0x00FB0A09,
616 0x00FC008A, 0x00FD0A0A,
617 0x00FE02A9, 0x00FF0062,
621 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0);
623 /* 1. make mask bitmap's dc */
624 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
625 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectBitmap(hDCMask
, hbmMask
);
627 /* 2. make masked Background bitmap */
629 /* 2.1 make bitmap */
630 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
631 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
632 hOldBitmap2
= (HBITMAP
)NtGdiSelectBitmap(hDC1
, hBitmap2
);
634 /* 2.2 draw dest bitmap and mask */
635 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
636 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
637 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
, 0, 0);
639 /* 3. make masked Foreground bitmap */
641 /* 3.1 make bitmap */
642 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
643 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
644 hOldBitmap3
= (HBITMAP
)NtGdiSelectBitmap(hDC2
, hBitmap3
);
646 /* 3.2 draw src bitmap and mask */
647 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
648 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
649 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
, 0, 0);
651 /* 4. combine both and copy the result to hdcDest */
652 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
, 0, 0);
653 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
, 0, 0);
655 /* 5. restore all objects */
656 NtGdiSelectBitmap(hDCMask
, hOldMaskBitmap
);
657 NtGdiSelectBitmap(hDC1
, hOldBitmap2
);
658 NtGdiSelectBitmap(hDC2
, hOldBitmap3
);
660 /* 6. delete all temp objects */
661 GreDeleteObject(hBitmap2
);
662 GreDeleteObject(hBitmap3
);
664 NtGdiDeleteObjectApp(hDC1
);
665 NtGdiDeleteObjectApp(hDC2
);
666 NtGdiDeleteObjectApp(hDCMask
);
684 IN DWORD crBackColor
)
703 IN DWORD dwBackColor
,
714 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
715 SURFACE
*BitmapMask
= NULL
;
721 XLATEOBJ
*XlateObj
= NULL
;
723 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
725 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
727 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
731 DPRINT("Locking DCs\n");
735 GDIOBJ_LockMultipleObjs(3, ahDC
, apObj
);
742 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
743 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
744 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
748 if (DCDest
->dctype
== DC_TYPE_INFO
)
750 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
751 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
752 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
753 /* Yes, Windows really returns TRUE in this case */
761 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
762 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
763 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
766 if (DCSrc
->dctype
== DC_TYPE_INFO
)
768 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
769 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
770 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
771 /* Yes, Windows really returns TRUE in this case */
777 DPRINT1("Getting a valid Source handle without using source!!!");
778 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
782 pdcattr
= DCDest
->pdcattr
;
784 DestRect
.left
= XOriginDest
;
785 DestRect
.top
= YOriginDest
;
786 DestRect
.right
= XOriginDest
+WidthDest
;
787 DestRect
.bottom
= YOriginDest
+HeightDest
;
788 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
790 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
791 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
792 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
793 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
795 SourceRect
.left
= XOriginSrc
;
796 SourceRect
.top
= YOriginSrc
;
797 SourceRect
.right
= XOriginSrc
+WidthSrc
;
798 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
802 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
804 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
805 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
806 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
807 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
813 /* Only prepare Source and Dest, hdcMask represents a DIB */
814 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
816 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
817 DC_vUpdateFillBrush(DCDest
);
819 /* Determine surfaces to be used in the bitblt */
820 BitmapDest
= DCDest
->dclevel
.pSurface
;
821 if (BitmapDest
== NULL
)
825 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
826 if (BitmapSrc
== NULL
)
829 /* Create the XLATEOBJ. */
830 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
831 XlateObj
= &exlo
.xlo
;
834 /* Offset the brush */
835 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
836 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
838 /* Make mask surface for source surface */
839 if (BitmapSrc
&& DCMask
)
841 BitmapMask
= DCMask
->dclevel
.pSurface
;
843 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
844 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
846 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
847 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
848 WidthSrc
, HeightSrc
);
849 EXLATEOBJ_vCleanup(&exlo
);
852 /* Create mask offset point */
853 MaskPoint
.x
= XOriginMask
;
854 MaskPoint
.y
= YOriginMask
;
855 IntLPtoDP(DCMask
, &MaskPoint
, 1);
856 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
857 MaskPoint
.y
+= DCMask
->ptlDCOrig
.x
;
860 /* Perform the bitblt operation */
861 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
863 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
864 DCDest
->rosdc
.CombinedClip
,
868 BitmapMask
? &MaskPoint
: NULL
,
869 &DCDest
->eboFill
.BrushObject
,
874 EXLATEOBJ_vCleanup(&exlo
);
878 DC_vFinishBlit(DCDest
, DCSrc
);
906 IN DWORD dwBackColor
)
908 return GreStretchBltMask(
945 if (pbrush
->flAttrs
& GDIBRUSH_IS_NULL
)
952 DestRect
.left
= XLeft
;
953 DestRect
.right
= XLeft
+ Width
;
957 DestRect
.left
= XLeft
+ Width
+ 1;
958 DestRect
.right
= XLeft
+ 1;
963 DestRect
.top
= YLeft
;
964 DestRect
.bottom
= YLeft
+ Height
;
968 DestRect
.top
= YLeft
+ Height
+ 1;
969 DestRect
.bottom
= YLeft
+ 1;
972 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
974 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
975 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
976 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
977 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
979 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
980 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
982 DC_vPrepareDCsForBlit(pdc
, DestRect
, NULL
, DestRect
);
984 psurf
= pdc
->dclevel
.pSurface
;
986 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
987 DC_vUpdateFillBrush(pdc
);
989 EBRUSHOBJ_vInit(&eboFill
, pbrush
, pdc
);
995 pdc
->rosdc
.CombinedClip
,
1000 &eboFill
.BrushObject
,
1002 ROP3_TO_ROP4(dwRop
));
1004 DC_vFinishBlit(pdc
, NULL
);
1006 EBRUSHOBJ_vCleanup(&eboFill
);
1023 pdc
= DC_LockDc(hDC
);
1026 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1030 if (pdc
->dctype
== DC_TYPE_INFO
)
1033 /* Yes, Windows really returns TRUE in this case */
1037 for (i
= 0; i
< cRects
; i
++)
1039 pbrush
= BRUSH_LockBrush(pRects
->hBrush
);
1050 BRUSH_UnlockBrush(pbrush
);
1075 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
1078 /* in this case we call on GdiMaskBlt */
1079 return NtGdiMaskBlt(hDC
, XLeft
, YLeft
, Width
, Height
, 0,0,0,0,0,0,ROP
,0);
1082 dc
= DC_LockDc(hDC
);
1085 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1088 if (dc
->dctype
== DC_TYPE_INFO
)
1091 /* Yes, Windows really returns TRUE in this case */
1095 pdcattr
= dc
->pdcattr
;
1097 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1098 DC_vUpdateFillBrush(dc
);
1100 pbrush
= BRUSH_LockBrush(pdcattr
->hbrush
);
1103 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1108 ret
= IntPatBlt(dc
, XLeft
, YLeft
, Width
, Height
, ROP
, pbrush
);
1110 BRUSH_UnlockBrush(pbrush
);
1120 IN PPOLYPATBLT pRects
,
1125 NTSTATUS Status
= STATUS_SUCCESS
;
1130 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, TAG_PATBLT
);
1133 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1138 ProbeForRead(pRects
,
1139 cRects
* sizeof(PATRECT
),
1143 cRects
* sizeof(PATRECT
));
1145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1147 Status
= _SEH2_GetExceptionCode();
1151 if (!NT_SUCCESS(Status
))
1153 ExFreePoolWithTag(rb
, TAG_PATBLT
);
1154 SetLastNtError(Status
);
1159 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
1162 ExFreePoolWithTag(rb
, TAG_PATBLT
);