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 EngSetLastError(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 EngSetLastError(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!!!\n");
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 ULONG TransparentColor
= 0;
335 DPRINT("Locking DCs\n");
338 GDIOBJ_LockMultipleObjs(2, ahDC
, apObj
);
342 if ((NULL
== DCDest
) || (NULL
== DCSrc
))
344 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst
, hdcSrc
);
345 EngSetLastError(ERROR_INVALID_HANDLE
);
346 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
347 if(DCDest
) GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
351 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
353 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
354 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
355 /* Yes, Windows really returns TRUE in this case */
361 rcDest
.right
= rcDest
.left
+ cxDst
;
362 rcDest
.bottom
= rcDest
.top
+ cyDst
;
363 IntLPtoDP(DCDest
, (LPPOINT
)&rcDest
, 2);
365 rcDest
.left
+= DCDest
->ptlDCOrig
.x
;
366 rcDest
.top
+= DCDest
->ptlDCOrig
.y
;
367 rcDest
.right
+= DCDest
->ptlDCOrig
.x
;
368 rcDest
.bottom
+= DCDest
->ptlDCOrig
.y
;
372 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
373 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
374 IntLPtoDP(DCSrc
, (LPPOINT
)&rcSrc
, 2);
376 rcSrc
.left
+= DCSrc
->ptlDCOrig
.x
;
377 rcSrc
.top
+= DCSrc
->ptlDCOrig
.y
;
378 rcSrc
.right
+= DCSrc
->ptlDCOrig
.x
;
379 rcSrc
.bottom
+= DCSrc
->ptlDCOrig
.y
;
381 /* Prepare for blit */
382 DC_vPrepareDCsForBlit(DCDest
, rcDest
, DCSrc
, rcSrc
);
384 BitmapDest
= DCDest
->dclevel
.pSurface
;
390 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
396 /* Translate Transparent (RGB) Color to the source palette */
397 EXLATEOBJ_vInitialize(&exlo
, &gpalRGB
, BitmapSrc
->ppal
, 0, 0, 0);
398 TransparentColor
= XLATEOBJ_iXlate(&exlo
.xlo
, (ULONG
)TransColor
);
399 EXLATEOBJ_vCleanup(&exlo
);
401 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
403 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
404 DCDest
->rosdc
.CombinedClip
, &exlo
.xlo
, &rcDest
, &rcSrc
,
405 TransparentColor
, 0);
407 EXLATEOBJ_vCleanup(&exlo
);
410 DC_vFinishBlit(DCDest
, DCSrc
);
411 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
412 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
417 /***********************************************************************
419 * Ported from WINE by sedwards 11-4-03
421 * Someone thought it would be faster to do it here and then switch back
422 * to GDI32. I dunno. Write a test and let me know.
423 * A. It should be in here!
426 static const DWORD ROP3Table
[256] =
428 0x000042, 0x010289, 0x020C89, 0x0300AA, 0x040C88, 0x0500A9, 0x060865, 0x0702C5,
429 0x080F08, 0x090245, 0x0A0329, 0x0B0B2A, 0x0C0324, 0x0D0B25, 0x0E08A5, 0x0F0001,
430 0x100C85, 0x1100A6, 0x120868, 0x1302C8, 0x140869, 0x1502C9, 0x165CCA, 0x171D54,
431 0x180D59, 0x191CC8, 0x1A06C5, 0x1B0768, 0x1C06CA, 0x1D0766, 0x1E01A5, 0x1F0385,
432 0x200F09, 0x210248, 0x220326, 0x230B24, 0x240D55, 0x251CC5, 0x2606C8, 0x271868,
433 0x280369, 0x2916CA, 0x2A0CC9, 0x2B1D58, 0x2C0784, 0x2D060A, 0x2E064A, 0x2F0E2A,
434 0x30032A, 0x310B28, 0x320688, 0x330008, 0x3406C4, 0x351864, 0x3601A8, 0x370388,
435 0x38078A, 0x390604, 0x3A0644, 0x3B0E24, 0x3C004A, 0x3D18A4, 0x3E1B24, 0x3F00EA,
436 0x400F0A, 0x410249, 0x420D5D, 0x431CC4, 0x440328, 0x450B29, 0x4606C6, 0x47076A,
437 0x480368, 0x4916C5, 0x4A0789, 0x4B0605, 0x4C0CC8, 0x4D1954, 0x4E0645, 0x4F0E25,
438 0x500325, 0x510B26, 0x5206C9, 0x530764, 0x5408A9, 0x550009, 0x5601A9, 0x570389,
439 0x580785, 0x590609, 0x5A0049, 0x5B18A9, 0x5C0649, 0x5D0E29, 0x5E1B29, 0x5F00E9,
440 0x600365, 0x6116C6, 0x620786, 0x630608, 0x640788, 0x650606, 0x660046, 0x6718A8,
441 0x6858A6, 0x690145, 0x6A01E9, 0x6B178A, 0x6C01E8, 0x6D1785, 0x6E1E28, 0x6F0C65,
442 0x700CC5, 0x711D5C, 0x720648, 0x730E28, 0x740646, 0x750E26, 0x761B28, 0x7700E6,
443 0x7801E5, 0x791786, 0x7A1E29, 0x7B0C68, 0x7C1E24, 0x7D0C69, 0x7E0955, 0x7F03C9,
444 0x8003E9, 0x810975, 0x820C49, 0x831E04, 0x840C48, 0x851E05, 0x8617A6, 0x8701C5,
445 0x8800C6, 0x891B08, 0x8A0E06, 0x8B0666, 0x8C0E08, 0x8D0668, 0x8E1D7C, 0x8F0CE5,
446 0x900C45, 0x911E08, 0x9217A9, 0x9301C4, 0x9417AA, 0x9501C9, 0x960169, 0x97588A,
447 0x981888, 0x990066, 0x9A0709, 0x9B07A8, 0x9C0704, 0x9D07A6, 0x9E16E6, 0x9F0345,
448 0xA000C9, 0xA11B05, 0xA20E09, 0xA30669, 0xA41885, 0xA50065, 0xA60706, 0xA707A5,
449 0xA803A9, 0xA90189, 0xAA0029, 0xAB0889, 0xAC0744, 0xAD06E9, 0xAE0B06, 0xAF0229,
450 0xB00E05, 0xB10665, 0xB21974, 0xB30CE8, 0xB4070A, 0xB507A9, 0xB616E9, 0xB70348,
451 0xB8074A, 0xB906E6, 0xBA0B09, 0xBB0226, 0xBC1CE4, 0xBD0D7D, 0xBE0269, 0xBF08C9,
452 0xC000CA, 0xC11B04, 0xC21884, 0xC3006A, 0xC40E04, 0xC50664, 0xC60708, 0xC707AA,
453 0xC803A8, 0xC90184, 0xCA0749, 0xCB06E4, 0xCC0020, 0xCD0888, 0xCE0B08, 0xCF0224,
454 0xD00E0A, 0xD1066A, 0xD20705, 0xD307A4, 0xD41D78, 0xD50CE9, 0xD616EA, 0xD70349,
455 0xD80745, 0xD906E8, 0xDA1CE9, 0xDB0D75, 0xDC0B04, 0xDD0228, 0xDE0268, 0xDF08C8,
456 0xE003A5, 0xE10185, 0xE20746, 0xE306EA, 0xE40748, 0xE506E5, 0xE61CE8, 0xE70D79,
457 0xE81D74, 0xE95CE6, 0xEA02E9, 0xEB0849, 0xEC02E8, 0xED0848, 0xEE0086, 0xEF0A08,
458 0xF00021, 0xF10885, 0xF20B05, 0xF3022A, 0xF40B0A, 0xF50225, 0xF60265, 0xF708C5,
459 0xF802E5, 0xF90845, 0xFA0089, 0xFB0A09, 0xFC008A, 0xFD0A0A, 0xFE02A9, 0xFF0062,
463 SwapROP3_SrcDst(BYTE bRop3
)
465 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
468 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
469 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
470 #define DSTCOPY 0x00AA0029
471 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
473 /* NOTE: An alternative algorithm could use a pattern brush, created from
474 * the mask bitmap and then use raster operation 0xCA to combine the fore
475 * and background bitmaps. In this case erasing the bits beforehand would be
476 * unneccessary. On the other hand the Operation does not provide an optimized
477 * version in the DIB code, while SRCAND and SRCPAINT do.
478 * A fully correct implementation would call Eng/DrvBitBlt, but our
479 * EngBitBlt completely ignores the mask surface.
483 * ------------------------------------------
484 * 0 0 0 0 0000xax = 000ax = 00x = 0
485 * 0 0 1 1 1001xax = 101ax = 10x = 1
486 * 0 1 0 0 0010xax = 001ax = 00x = 0
487 * 0 1 1 1 1011xax = 100ax = 10x = 1
488 * 1 0 0 0 0100xax = 010ax = 00x = 0
489 * 1 0 1 0 1101xax = 111ax = 11x = 0
490 * 1 1 0 1 0110xax = 011ax = 01x = 1
491 * 1 1 1 1 1111xax = 110ax = 10x = 1
493 * Operation index = 11001010 = 0xCA = PSaDPnao = DPSDxax
494 * ^ no, this is not random letters, its reverse Polish notation
511 IN DWORD crBackColor
)
513 HBITMAP hbmFore
, hbmBack
;
514 HDC hdcMask
, hdcFore
, hdcBack
;
517 COLORREF crFore
, crBack
;
520 return NtGdiBitBlt(hdcDest
,
532 /* Lock the dest DC */
533 pdc
= DC_LockDc(hdcDest
);
534 if (!pdc
) return FALSE
;
536 /* Get brush and colors from dest dc */
537 hbr
= pdc
->pdcattr
->hbrush
;
538 crFore
= pdc
->pdcattr
->crForegroundClr
;
539 crBack
= pdc
->pdcattr
->crBackgroundClr
;
544 /* 1. Create mask bitmap's dc */
545 hdcMask
= NtGdiCreateCompatibleDC(hdcDest
);
546 NtGdiSelectBitmap(hdcMask
, hbmMask
);
548 /* 2. Create masked Background bitmap */
550 /* 2.1 Create bitmap */
551 hdcBack
= NtGdiCreateCompatibleDC(hdcDest
);
552 hbmBack
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
553 NtGdiSelectBitmap(hdcBack
, hbmBack
);
555 /* 2.2 Copy source bitmap */
556 NtGdiSelectBrush(hdcBack
, hbr
);
557 IntGdiSetBkColor(hdcBack
, crBack
);
558 IntGdiSetTextColor(hdcBack
, crFore
);
559 NtGdiBitBlt(hdcBack
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
561 /* 2.3 Do the background rop */
562 NtGdiBitBlt(hdcBack
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
564 /* 2.4 Erase the foreground pixels */
565 IntGdiSetBkColor(hdcBack
, 0xffffffff);
566 IntGdiSetTextColor(hdcBack
, 0);
567 NtGdiBitBlt(hdcBack
, 0, 0, nWidth
, nHeight
, hdcMask
, xMask
, yMask
, SRCAND
, 0, 0);
569 /* 3. Create masked Foreground bitmap */
571 /* 3.1 Create bitmap */
572 hdcFore
= NtGdiCreateCompatibleDC(hdcDest
);
573 hbmFore
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
574 NtGdiSelectBitmap(hdcFore
, hbmFore
);
576 /* 3.2 Copy the dest bitmap */
577 NtGdiSelectBrush(hdcFore
, hbr
);
578 IntGdiSetBkColor(hdcFore
, crBack
);
579 IntGdiSetTextColor(hdcFore
, crFore
);
580 NtGdiBitBlt(hdcFore
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
582 /* 2.3 Do the foreground rop */
583 NtGdiBitBlt(hdcFore
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
585 /* 2.4 Erase the background pixels */
586 IntGdiSetBkColor(hdcFore
, 0);
587 IntGdiSetTextColor(hdcFore
, 0xffffffff);
588 NtGdiBitBlt(hdcFore
, 0, 0, nWidth
, nHeight
, hdcMask
, xMask
, yMask
, SRCAND
, 0, 0);
590 /* 3. Combine the fore and background into the background bitmap */
591 NtGdiBitBlt(hdcBack
, 0, 0, nWidth
, nHeight
, hdcFore
, 0, 0, SRCPAINT
, 0, 0);
593 /* 4. Copy the result to hdcDest */
594 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcBack
, 0, 0, SRCCOPY
, 0, 0);
596 /* 5. delete all temp objects */
597 NtGdiDeleteObjectApp(hdcBack
);
598 NtGdiDeleteObjectApp(hdcFore
);
599 NtGdiDeleteObjectApp(hdcMask
);
600 GreDeleteObject(hbmFore
);
601 GreDeleteObject(hbmBack
);
619 IN DWORD crBackColor
)
638 IN DWORD dwBackColor
,
649 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
650 SURFACE
*BitmapMask
= NULL
;
656 XLATEOBJ
*XlateObj
= NULL
;
658 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
660 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
662 EngSetLastError(ERROR_INVALID_PARAMETER
);
666 DPRINT("Locking DCs\n");
670 GDIOBJ_LockMultipleObjs(3, ahDC
, apObj
);
677 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
678 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
679 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
683 if (DCDest
->dctype
== DC_TYPE_INFO
)
685 if(DCSrc
) GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
686 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
687 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
688 /* Yes, Windows really returns TRUE in this case */
696 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
697 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
698 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
701 if (DCSrc
->dctype
== DC_TYPE_INFO
)
703 GDIOBJ_UnlockObjByPtr(&DCDest
->BaseObject
);
704 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
705 if(DCMask
) GDIOBJ_UnlockObjByPtr(&DCMask
->BaseObject
);
706 /* Yes, Windows really returns TRUE in this case */
712 DPRINT1("Getting a valid Source handle without using source!!!\n");
713 GDIOBJ_UnlockObjByPtr(&DCSrc
->BaseObject
);
717 pdcattr
= DCDest
->pdcattr
;
719 DestRect
.left
= XOriginDest
;
720 DestRect
.top
= YOriginDest
;
721 DestRect
.right
= XOriginDest
+WidthDest
;
722 DestRect
.bottom
= YOriginDest
+HeightDest
;
723 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
725 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
726 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
727 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
728 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
730 SourceRect
.left
= XOriginSrc
;
731 SourceRect
.top
= YOriginSrc
;
732 SourceRect
.right
= XOriginSrc
+WidthSrc
;
733 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
737 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
739 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
740 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
741 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
742 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
748 /* Only prepare Source and Dest, hdcMask represents a DIB */
749 DC_vPrepareDCsForBlit(DCDest
, DestRect
, DCSrc
, SourceRect
);
751 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
752 DC_vUpdateFillBrush(DCDest
);
754 /* Determine surfaces to be used in the bitblt */
755 BitmapDest
= DCDest
->dclevel
.pSurface
;
756 if (BitmapDest
== NULL
)
760 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
761 if (BitmapSrc
== NULL
)
764 /* Create the XLATEOBJ. */
765 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
766 XlateObj
= &exlo
.xlo
;
769 /* Offset the brush */
770 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
771 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
773 /* Make mask surface for source surface */
774 if (BitmapSrc
&& DCMask
)
776 BitmapMask
= DCMask
->dclevel
.pSurface
;
778 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
779 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
781 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
782 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
783 WidthSrc
, HeightSrc
);
784 EXLATEOBJ_vCleanup(&exlo
);
787 /* Create mask offset point */
788 MaskPoint
.x
= XOriginMask
;
789 MaskPoint
.y
= YOriginMask
;
790 IntLPtoDP(DCMask
, &MaskPoint
, 1);
791 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
792 MaskPoint
.y
+= DCMask
->ptlDCOrig
.x
;
795 /* Perform the bitblt operation */
796 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
798 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
799 DCDest
->rosdc
.CombinedClip
,
803 BitmapMask
? &MaskPoint
: NULL
,
804 &DCDest
->eboFill
.BrushObject
,
809 EXLATEOBJ_vCleanup(&exlo
);
813 DC_vFinishBlit(DCDest
, DCSrc
);
841 IN DWORD dwBackColor
)
843 return GreStretchBltMask(
880 if (pbrush
->flAttrs
& GDIBRUSH_IS_NULL
)
887 DestRect
.left
= XLeft
;
888 DestRect
.right
= XLeft
+ Width
;
892 DestRect
.left
= XLeft
+ Width
+ 1;
893 DestRect
.right
= XLeft
+ 1;
898 DestRect
.top
= YLeft
;
899 DestRect
.bottom
= YLeft
+ Height
;
903 DestRect
.top
= YLeft
+ Height
+ 1;
904 DestRect
.bottom
= YLeft
+ 1;
907 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
909 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
910 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
911 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
912 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
914 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
915 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
917 DC_vPrepareDCsForBlit(pdc
, DestRect
, NULL
, DestRect
);
919 psurf
= pdc
->dclevel
.pSurface
;
921 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
922 DC_vUpdateFillBrush(pdc
);
924 EBRUSHOBJ_vInit(&eboFill
, pbrush
, pdc
);
930 pdc
->rosdc
.CombinedClip
,
935 &eboFill
.BrushObject
,
937 ROP3_TO_ROP4(dwRop
));
939 DC_vFinishBlit(pdc
, NULL
);
941 EBRUSHOBJ_vCleanup(&eboFill
);
958 pdc
= DC_LockDc(hDC
);
961 EngSetLastError(ERROR_INVALID_HANDLE
);
965 if (pdc
->dctype
== DC_TYPE_INFO
)
968 /* Yes, Windows really returns TRUE in this case */
972 for (i
= 0; i
< cRects
; i
++)
974 pbrush
= BRUSH_LockBrush(pRects
->hBrush
);
985 BRUSH_UnlockBrush(pbrush
);
1010 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
1013 /* in this case we call on GdiMaskBlt */
1014 return NtGdiMaskBlt(hDC
, XLeft
, YLeft
, Width
, Height
, 0,0,0,0,0,0,ROP
,0);
1017 dc
= DC_LockDc(hDC
);
1020 EngSetLastError(ERROR_INVALID_HANDLE
);
1023 if (dc
->dctype
== DC_TYPE_INFO
)
1026 /* Yes, Windows really returns TRUE in this case */
1030 pdcattr
= dc
->pdcattr
;
1032 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1033 DC_vUpdateFillBrush(dc
);
1035 pbrush
= BRUSH_LockBrush(pdcattr
->hbrush
);
1038 EngSetLastError(ERROR_INVALID_HANDLE
);
1043 ret
= IntPatBlt(dc
, XLeft
, YLeft
, Width
, Height
, ROP
, pbrush
);
1045 BRUSH_UnlockBrush(pbrush
);
1055 IN PPOLYPATBLT pRects
,
1060 NTSTATUS Status
= STATUS_SUCCESS
;
1065 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, GDITAG_PLGBLT_DATA
);
1068 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1073 ProbeForRead(pRects
,
1074 cRects
* sizeof(PATRECT
),
1078 cRects
* sizeof(PATRECT
));
1080 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1082 Status
= _SEH2_GetExceptionCode();
1086 if (!NT_SUCCESS(Status
))
1088 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1089 SetLastNtError(Status
);
1094 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
1097 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);