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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define IN_RECT(r,x,y) \
50 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
52 POINTL SourcePoint
, BrushOrigin
;
54 XLATEOBJ
*XlateObj
= NULL
;
55 HPALETTE SourcePalette
= 0, DestPalette
= 0;
56 PGDIBRUSHOBJ BrushObj
;
57 GDIBRUSHINST BrushInst
;
58 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
59 BOOL UsesPattern
= ROP3_USES_PATTERN(ROP
);
61 DCDest
= DC_LockDc(hDCDest
);
64 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
65 SetLastWin32Error(ERROR_INVALID_HANDLE
);
71 /* Yes, Windows really returns TRUE in this case */
77 if (hDCSrc
!= hDCDest
)
79 DCSrc
= DC_LockDc(hDCSrc
);
83 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
84 SetLastWin32Error(ERROR_INVALID_HANDLE
);
91 /* Yes, Windows really returns TRUE in this case */
105 /* Offset the destination and source by the origin of their DCs. */
106 XDest
+= DCDest
->w
.DCOrgX
;
107 YDest
+= DCDest
->w
.DCOrgY
;
110 XSrc
+= DCSrc
->w
.DCOrgX
;
111 YSrc
+= DCSrc
->w
.DCOrgY
;
114 DestRect
.left
= XDest
;
115 DestRect
.top
= YDest
;
116 DestRect
.right
= XDest
+Width
;
117 DestRect
.bottom
= YDest
+Height
;
119 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
121 SourcePoint
.x
= XSrc
;
122 SourcePoint
.y
= YSrc
;
127 /* Determine surfaces to be used in the bitblt */
128 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
131 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
132 BitmapSrc
= BitmapDest
;
134 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
143 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->Dc_Attr
.hbrush
);
144 if (NULL
== BrushObj
)
146 if (UsesSource
&& hDCSrc
!= hDCDest
)
150 if(BitmapDest
!= NULL
)
152 BITMAPOBJ_UnlockBitmap(BitmapDest
);
154 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
156 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
159 SetLastWin32Error(ERROR_INVALID_HANDLE
);
162 BrushOrigin
= *((PPOINTL
)&BrushObj
->ptOrigin
);
163 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
170 /* Create the XLATEOBJ. */
173 if (DCDest
->w
.hPalette
!= 0)
174 DestPalette
= DCDest
->w
.hPalette
;
176 if (DCSrc
->w
.hPalette
!= 0)
177 SourcePalette
= DCSrc
->w
.hPalette
;
179 /* KB41464 details how to convert between mono and color */
180 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
186 if (DCDest
->w
.bitsPerPixel
== 1)
188 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->Dc_Attr
.crBackgroundClr
);
190 else if (DCSrc
->w
.bitsPerPixel
== 1)
192 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->Dc_Attr
.crBackgroundClr
, DCSrc
->Dc_Attr
.crForegroundClr
);
196 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
198 if (NULL
== XlateObj
)
200 if (UsesSource
&& hDCSrc
!= hDCDest
)
205 if(BitmapDest
!= NULL
)
207 BITMAPOBJ_UnlockBitmap(BitmapDest
);
209 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
211 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
215 BRUSHOBJ_UnlockBrush(BrushObj
);
217 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
223 /* Perform the bitblt operation */
224 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
, NULL
,
225 DCDest
->CombinedClip
, XlateObj
, &DestRect
,
227 BrushObj
? &BrushInst
.BrushObject
: NULL
,
228 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
230 if (UsesSource
&& XlateObj
!= NULL
)
231 EngDeleteXlate(XlateObj
);
233 if(BitmapDest
!= NULL
)
235 BITMAPOBJ_UnlockBitmap(BitmapDest
);
237 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
239 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
241 if (BrushObj
!= NULL
)
243 BRUSHOBJ_UnlockBrush(BrushObj
);
245 if (UsesSource
&& hDCSrc
!= hDCDest
)
270 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
272 HPALETTE SourcePalette
= 0, DestPalette
= 0;
273 PPALGDI PalDestGDI
, PalSourceGDI
;
274 USHORT PalDestMode
, PalSrcMode
;
275 ULONG TransparentColor
= 0;
278 if(!(DCDest
= DC_LockDc(hdcDst
)))
280 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
281 SetLastWin32Error(ERROR_INVALID_HANDLE
);
287 /* Yes, Windows really returns TRUE in this case */
291 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
294 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
295 SetLastWin32Error(ERROR_INVALID_HANDLE
);
309 /* Yes, Windows really returns TRUE in this case */
313 /* Offset positions */
314 xDst
+= DCDest
->w
.DCOrgX
;
315 yDst
+= DCDest
->w
.DCOrgY
;
316 xSrc
+= DCSrc
->w
.DCOrgX
;
317 ySrc
+= DCSrc
->w
.DCOrgY
;
319 if(DCDest
->w
.hPalette
)
320 DestPalette
= DCDest
->w
.hPalette
;
322 if(DCSrc
->w
.hPalette
)
323 SourcePalette
= DCSrc
->w
.hPalette
;
325 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
329 SetLastWin32Error(ERROR_INVALID_HANDLE
);
332 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
334 PALETTE_UnlockPalette(PalSourceGDI
);
337 SetLastWin32Error(ERROR_INVALID_HANDLE
);
340 if(DestPalette
!= SourcePalette
)
342 PalDestMode
= PalDestGDI
->Mode
;
343 PalSrcMode
= PalSourceGDI
->Mode
;
344 PALETTE_UnlockPalette(PalDestGDI
);
348 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
350 PALETTE_UnlockPalette(PalSourceGDI
);
352 /* Translate Transparent (RGB) Color to the source palette */
353 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
355 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
356 EngDeleteXlate(XlateObj
);
359 /* Create the XLATE object to convert colors between source and destination */
360 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
362 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
363 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
365 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
366 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
371 rcDest
.right
= rcDest
.left
+ cxDst
;
372 rcDest
.bottom
= rcDest
.top
+ cyDst
;
375 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
376 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
378 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
380 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
384 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
385 DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
386 TransparentColor
, 0);
389 BITMAPOBJ_UnlockBitmap(BitmapDest
);
390 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
398 EngDeleteXlate(XlateObj
);
409 IN OPTIONAL LPBYTE pUnsafeBits
)
416 /* NOTE: Windows also doesn't store nr. of planes separately! */
417 BitsPixel
= BitsPixel
* Planes
;
418 WidthBytes
= BITMAPOBJ_GetWidthBytes(Width
, BitsPixel
);
420 /* Check parameters */
421 if (0 == Height
|| 0 == Width
)
423 Size
.cx
= Size
.cy
= 1;
427 Size
.cx
= abs(Width
);
428 Size
.cy
= abs(Height
);
431 /* Create the bitmap object. */
432 hBitmap
= IntCreateBitmap(Size
, WidthBytes
,
433 BitmapFormat(BitsPixel
, BI_RGB
),
434 (Height
< 0 ? BMF_TOPDOWN
: 0) |
435 (NULL
== pUnsafeBits
? 0 : BMF_NOZEROINIT
), NULL
);
438 DPRINT("NtGdiCreateBitmap: returned 0\n");
442 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
443 Size
.cx
, Size
.cy
, BitsPixel
, hBitmap
);
445 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
448 /* FIXME should we free the hBitmap or return it ?? */
452 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
454 if (NULL
!= pUnsafeBits
)
458 ProbeForRead(pUnsafeBits
, bmp
->SurfObj
.cjBits
, 1);
459 IntSetBitmapBits(bmp
, bmp
->SurfObj
.cjBits
, pUnsafeBits
);
467 BITMAPOBJ_UnlockBitmap( bmp
);
473 BITMAP_Cleanup(PVOID ObjectBody
)
475 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
476 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
477 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
479 if (pBmp
->dib
== NULL
)
481 if (pBmp
->SurfObj
.pvBits
!= NULL
)
482 ExFreePool(pBmp
->SurfObj
.pvBits
);
486 if (pBmp
->SurfObj
.pvBits
!= NULL
)
487 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
489 if (pBmp
->hDIBPalette
!= NULL
)
491 NtGdiDeleteObject(pBmp
->hDIBPalette
);
495 if (NULL
!= pBmp
->BitsLock
)
497 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
498 pBmp
->BitsLock
= NULL
;
506 IntCreateCompatibleBitmap(
515 if ((Width
>= 0x10000) || (Height
>= 0x10000))
517 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
521 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
522 if (0 == Width
|| 0 == Height
)
524 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
528 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
535 NtGdiCreateCompatibleBitmap(
545 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
549 SetLastWin32Error(ERROR_INVALID_HANDLE
);
553 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
555 DPRINT ("\t\t%04x\n", Bmp
);
568 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
570 /* lie and say we succeded */
575 NtGdiGetBitmapDimension(
581 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
587 *Dimension
= bmp
->dimension
;
589 BITMAPOBJ_UnlockBitmap(bmp
);
595 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
598 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
599 BOOL bInRect
= FALSE
;
600 BITMAPOBJ
*BitmapObject
;
601 SURFOBJ
*SurfaceObject
;
606 dc
= DC_LockDc (hDC
);
610 SetLastWin32Error(ERROR_INVALID_HANDLE
);
618 XPos
+= dc
->w
.DCOrgX
;
619 YPos
+= dc
->w
.DCOrgY
;
620 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
623 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
624 SurfaceObject
= &BitmapObject
->SurfObj
;
627 if ( dc
->w
.hPalette
!= 0 )
628 Pal
= dc
->w
.hPalette
;
629 /* FIXME: Verify if it shouldn't be PAL_BGR! */
630 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
633 // check if this DC has a DIB behind it...
634 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
636 ASSERT ( SurfaceObject
->lDelta
);
637 Result
= XLATEOBJ_iXlate(XlateObj
,
638 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
640 EngDeleteXlate(XlateObj
);
642 BITMAPOBJ_UnlockBitmap(BitmapObject
);
647 // if Result is still CLR_INVALID, then the "quick" method above didn't work
648 if ( bInRect
&& Result
== CLR_INVALID
)
650 // FIXME: create a 1x1 32BPP DIB, and blit to it
651 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
654 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
656 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
657 hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
658 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
661 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
666 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
, 0, 0 );
667 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
669 // our bitmap is no longer selected, so we can access it's stuff...
670 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
673 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
674 BITMAPOBJ_UnlockBitmap ( bmpobj
);
677 NtGdiDeleteObject ( hBmpTmp
);
679 NtGdiDeleteObjectApp ( hDCTmp
);
686 /***********************************************************************
688 * Ported from WINE by sedwards 11-4-03
690 * Someone thought it would be faster to do it here and then switch back
691 * to GDI32. I dunno. Write a test and let me know.
695 SwapROP3_SrcDst(BYTE bRop3
)
697 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
700 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
701 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
702 #define DSTCOPY 0x00AA0029
703 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
707 HDC hdcDest
, INT nXDest
, INT nYDest
,
708 INT nWidth
, INT nHeight
, HDC hdcSrc
,
709 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
710 INT xMask
, INT yMask
, DWORD dwRop
,
711 IN DWORD crBackColor
)
713 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
714 HDC hDCMask
, hDC1
, hDC2
;
715 static const DWORD ROP3Table
[256] =
717 0x00000042, 0x00010289,
718 0x00020C89, 0x000300AA,
719 0x00040C88, 0x000500A9,
720 0x00060865, 0x000702C5,
721 0x00080F08, 0x00090245,
722 0x000A0329, 0x000B0B2A,
723 0x000C0324, 0x000D0B25,
724 0x000E08A5, 0x000F0001,
725 0x00100C85, 0x001100A6,
726 0x00120868, 0x001302C8,
727 0x00140869, 0x001502C9,
728 0x00165CCA, 0x00171D54,
729 0x00180D59, 0x00191CC8,
730 0x001A06C5, 0x001B0768,
731 0x001C06CA, 0x001D0766,
732 0x001E01A5, 0x001F0385,
733 0x00200F09, 0x00210248,
734 0x00220326, 0x00230B24,
735 0x00240D55, 0x00251CC5,
736 0x002606C8, 0x00271868,
737 0x00280369, 0x002916CA,
738 0x002A0CC9, 0x002B1D58,
739 0x002C0784, 0x002D060A,
740 0x002E064A, 0x002F0E2A,
741 0x0030032A, 0x00310B28,
742 0x00320688, 0x00330008,
743 0x003406C4, 0x00351864,
744 0x003601A8, 0x00370388,
745 0x0038078A, 0x00390604,
746 0x003A0644, 0x003B0E24,
747 0x003C004A, 0x003D18A4,
748 0x003E1B24, 0x003F00EA,
749 0x00400F0A, 0x00410249,
750 0x00420D5D, 0x00431CC4,
751 0x00440328, 0x00450B29,
752 0x004606C6, 0x0047076A,
753 0x00480368, 0x004916C5,
754 0x004A0789, 0x004B0605,
755 0x004C0CC8, 0x004D1954,
756 0x004E0645, 0x004F0E25,
757 0x00500325, 0x00510B26,
758 0x005206C9, 0x00530764,
759 0x005408A9, 0x00550009,
760 0x005601A9, 0x00570389,
761 0x00580785, 0x00590609,
762 0x005A0049, 0x005B18A9,
763 0x005C0649, 0x005D0E29,
764 0x005E1B29, 0x005F00E9,
765 0x00600365, 0x006116C6,
766 0x00620786, 0x00630608,
767 0x00640788, 0x00650606,
768 0x00660046, 0x006718A8,
769 0x006858A6, 0x00690145,
770 0x006A01E9, 0x006B178A,
771 0x006C01E8, 0x006D1785,
772 0x006E1E28, 0x006F0C65,
773 0x00700CC5, 0x00711D5C,
774 0x00720648, 0x00730E28,
775 0x00740646, 0x00750E26,
776 0x00761B28, 0x007700E6,
777 0x007801E5, 0x00791786,
778 0x007A1E29, 0x007B0C68,
779 0x007C1E24, 0x007D0C69,
780 0x007E0955, 0x007F03C9,
781 0x008003E9, 0x00810975,
782 0x00820C49, 0x00831E04,
783 0x00840C48, 0x00851E05,
784 0x008617A6, 0x008701C5,
785 0x008800C6, 0x00891B08,
786 0x008A0E06, 0x008B0666,
787 0x008C0E08, 0x008D0668,
788 0x008E1D7C, 0x008F0CE5,
789 0x00900C45, 0x00911E08,
790 0x009217A9, 0x009301C4,
791 0x009417AA, 0x009501C9,
792 0x00960169, 0x0097588A,
793 0x00981888, 0x00990066,
794 0x009A0709, 0x009B07A8,
795 0x009C0704, 0x009D07A6,
796 0x009E16E6, 0x009F0345,
797 0x00A000C9, 0x00A11B05,
798 0x00A20E09, 0x00A30669,
799 0x00A41885, 0x00A50065,
800 0x00A60706, 0x00A707A5,
801 0x00A803A9, 0x00A90189,
802 0x00AA0029, 0x00AB0889,
803 0x00AC0744, 0x00AD06E9,
804 0x00AE0B06, 0x00AF0229,
805 0x00B00E05, 0x00B10665,
806 0x00B21974, 0x00B30CE8,
807 0x00B4070A, 0x00B507A9,
808 0x00B616E9, 0x00B70348,
809 0x00B8074A, 0x00B906E6,
810 0x00BA0B09, 0x00BB0226,
811 0x00BC1CE4, 0x00BD0D7D,
812 0x00BE0269, 0x00BF08C9,
813 0x00C000CA, 0x00C11B04,
814 0x00C21884, 0x00C3006A,
815 0x00C40E04, 0x00C50664,
816 0x00C60708, 0x00C707AA,
817 0x00C803A8, 0x00C90184,
818 0x00CA0749, 0x00CB06E4,
819 0x00CC0020, 0x00CD0888,
820 0x00CE0B08, 0x00CF0224,
821 0x00D00E0A, 0x00D1066A,
822 0x00D20705, 0x00D307A4,
823 0x00D41D78, 0x00D50CE9,
824 0x00D616EA, 0x00D70349,
825 0x00D80745, 0x00D906E8,
826 0x00DA1CE9, 0x00DB0D75,
827 0x00DC0B04, 0x00DD0228,
828 0x00DE0268, 0x00DF08C8,
829 0x00E003A5, 0x00E10185,
830 0x00E20746, 0x00E306EA,
831 0x00E40748, 0x00E506E5,
832 0x00E61CE8, 0x00E70D79,
833 0x00E81D74, 0x00E95CE6,
834 0x00EA02E9, 0x00EB0849,
835 0x00EC02E8, 0x00ED0848,
836 0x00EE0086, 0x00EF0A08,
837 0x00F00021, 0x00F10885,
838 0x00F20B05, 0x00F3022A,
839 0x00F40B0A, 0x00F50225,
840 0x00F60265, 0x00F708C5,
841 0x00F802E5, 0x00F90845,
842 0x00FA0089, 0x00FB0A09,
843 0x00FC008A, 0x00FD0A0A,
844 0x00FE02A9, 0x00FF0062,
848 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0);
850 /* 1. make mask bitmap's dc */
851 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
852 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
854 /* 2. make masked Background bitmap */
856 /* 2.1 make bitmap */
857 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
858 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
859 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
861 /* 2.2 draw dest bitmap and mask */
862 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
863 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
864 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
, 0, 0);
866 /* 3. make masked Foreground bitmap */
868 /* 3.1 make bitmap */
869 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
870 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
871 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
873 /* 3.2 draw src bitmap and mask */
874 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
875 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
876 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
, 0, 0);
878 /* 4. combine two bitmap and copy it to hdcDest */
879 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
, 0, 0);
880 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
, 0, 0);
882 /* 5. restore all object */
883 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
884 NtGdiSelectObject(hDC1
, hOldBitmap2
);
885 NtGdiSelectObject(hDC2
, hOldBitmap3
);
887 /* 6. delete all temp object */
888 NtGdiDeleteObject(hBitmap2
);
889 NtGdiDeleteObject(hBitmap3
);
891 NtGdiDeleteObjectApp(hDC1
);
892 NtGdiDeleteObjectApp(hDC2
);
893 NtGdiDeleteObjectApp(hDCMask
);
911 IN DWORD crBackColor
)
928 /* Don't copy more bytes than the buffer has */
929 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
932 /* FIXME: Call DDI CopyBits here if available */
935 DPRINT("Calling device specific BitmapBits\n");
936 if(bmp
->DDBitmap
->funcs
->pBitmapBits
)
938 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hbitmap
, bits
, count
, DDB_GET
);
942 ERR_(bitmap
)("BitmapBits == NULL??\n");
949 RtlCopyMemory(Bits
, bmp
->SurfObj
.pvBits
, Bytes
);
956 NtGdiGetBitmapBits(HBITMAP hBitmap
,
958 OUT OPTIONAL PBYTE pUnsafeBits
)
963 if (pUnsafeBits
!= NULL
&& Bytes
== 0)
968 bmp
= BITMAPOBJ_LockBitmap (hBitmap
);
971 SetLastWin32Error(ERROR_INVALID_HANDLE
);
975 /* If the bits vector is null, the function should return the read size */
976 if (pUnsafeBits
== NULL
)
978 ret
= bmp
->SurfObj
.cjBits
;
979 BITMAPOBJ_UnlockBitmap (bmp
);
983 /* Don't copy more bytes than the buffer has */
984 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
988 ProbeForWrite(pUnsafeBits
, Bytes
, 1);
989 ret
= IntGetBitmapBits(bmp
, Bytes
, pUnsafeBits
);
997 BITMAPOBJ_UnlockBitmap (bmp
);
1011 /* Don't copy more bytes than the buffer has */
1012 Bytes
= min(Bytes
, bmp
->SurfObj
.cjBits
);
1015 /* FIXME: call DDI specific function here if available */
1018 DPRINT ("Calling device specific BitmapBits\n");
1019 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
1021 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
1025 DPRINT ("BitmapBits == NULL??\n");
1032 RtlCopyMemory(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
1044 IN PBYTE pUnsafeBits
)
1049 if (pUnsafeBits
== NULL
|| Bytes
== 0)
1054 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1057 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1063 ProbeForRead(pUnsafeBits
, Bytes
, 1);
1064 ret
= IntSetBitmapBits(bmp
, Bytes
, pUnsafeBits
);
1072 BITMAPOBJ_UnlockBitmap(bmp
);
1078 NtGdiSetBitmapDimension(
1086 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1094 *Size
= bmp
->dimension
;
1096 bmp
->dimension
.cx
= Width
;
1097 bmp
->dimension
.cy
= Height
;
1099 BITMAPOBJ_UnlockBitmap (bmp
);
1112 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1115 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1117 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1119 Color
= NtGdiGetPixel(hDC
,X
,Y
);
1120 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1124 Color
= ((COLORREF
) -1);
1125 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1136 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
, NULL
);
1139 if (NewBrush
== NULL
)
1141 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1142 if (OldBrush
== NULL
)
1144 NtGdiDeleteObject(NewBrush
);
1147 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1148 NtGdiSelectObject(hDC
, OldBrush
);
1149 NtGdiDeleteObject(NewBrush
);
1166 IN DWORD dwBackColor
)
1170 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1174 XLATEOBJ
*XlateObj
= NULL
;
1175 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1176 PGDIBRUSHOBJ BrushObj
;
1177 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1178 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1180 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1182 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1185 DCDest
= DC_LockDc(hDCDest
);
1188 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1189 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1194 DC_UnlockDc(DCDest
);
1195 /* Yes, Windows really returns TRUE in this case */
1201 if (hDCSrc
!= hDCDest
)
1203 DCSrc
= DC_LockDc(hDCSrc
);
1206 DC_UnlockDc(DCDest
);
1207 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1208 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1214 DC_UnlockDc(DCDest
);
1215 /* Yes, Windows really returns TRUE in this case */
1229 /* Offset the destination and source by the origin of their DCs. */
1230 XOriginDest
+= DCDest
->w
.DCOrgX
;
1231 YOriginDest
+= DCDest
->w
.DCOrgY
;
1234 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1235 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1238 DestRect
.left
= XOriginDest
;
1239 DestRect
.top
= YOriginDest
;
1240 DestRect
.right
= XOriginDest
+WidthDest
;
1241 DestRect
.bottom
= YOriginDest
+HeightDest
;
1243 SourceRect
.left
= XOriginSrc
;
1244 SourceRect
.top
= YOriginSrc
;
1245 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1246 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1248 /* Determine surfaces to be used in the bitblt */
1249 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1252 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1253 BitmapSrc
= BitmapDest
;
1255 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1264 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1265 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1266 if ( SourceRect
.left
< 0 )
1268 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1269 SourceRect
.left
= 0;
1271 if ( SourceRect
.top
< 0 )
1273 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1276 if ( SourceRect
.right
< -1 )
1278 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1279 SourceRect
.right
= -1;
1281 if ( SourceRect
.bottom
< -1 )
1283 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1284 SourceRect
.bottom
= -1;
1286 if ( SourceRect
.right
> sw
)
1288 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1289 SourceRect
.right
= sw
;
1291 if ( SourceRect
.bottom
> sh
)
1293 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1294 SourceRect
.bottom
= sh
;
1298 if ( SourceRect
.left
> sw
)
1300 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1301 SourceRect
.left
= 0;
1303 if ( SourceRect
.top
> sh
)
1305 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1308 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1310 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1318 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->Dc_Attr
.hbrush
);
1319 if (NULL
== BrushObj
)
1321 if (UsesSource
&& hDCSrc
!= hDCDest
)
1325 DC_UnlockDc(DCDest
);
1326 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1335 /* Create the XLATEOBJ. */
1338 if (DCDest
->w
.hPalette
!= 0)
1339 DestPalette
= DCDest
->w
.hPalette
;
1341 if (DCSrc
->w
.hPalette
!= 0)
1342 SourcePalette
= DCSrc
->w
.hPalette
;
1344 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1345 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1346 if (NULL
== XlateObj
)
1348 if (UsesSource
&& hDCSrc
!= hDCDest
)
1352 DC_UnlockDc(DCDest
);
1353 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1358 /* Perform the bitblt operation */
1359 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1360 NULL
, DCDest
->CombinedClip
, XlateObj
,
1361 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1365 EngDeleteXlate(XlateObj
);
1368 BRUSHOBJ_UnlockBrush(BrushObj
);
1371 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1373 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1375 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1376 if (UsesSource
&& hDCSrc
!= hDCDest
)
1380 DC_UnlockDc(DCDest
);
1397 BLENDFUNCTION BlendFunc
,
1402 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1403 RECTL DestRect
, SourceRect
;
1407 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1408 BlendObj
.BlendFunction
= BlendFunc
;
1410 DCDest
= DC_LockDc(hDCDest
);
1413 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
);
1414 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1419 DC_UnlockDc(DCDest
);
1420 /* Yes, Windows really returns TRUE in this case */
1424 if (hDCSrc
!= hDCDest
)
1426 DCSrc
= DC_LockDc(hDCSrc
);
1429 DC_UnlockDc(DCDest
);
1430 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc
);
1431 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1437 DC_UnlockDc(DCDest
);
1438 /* Yes, Windows really returns TRUE in this case */
1447 /* Offset the destination and source by the origin of their DCs. */
1448 XOriginDest
+= DCDest
->w
.DCOrgX
;
1449 YOriginDest
+= DCDest
->w
.DCOrgY
;
1450 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1451 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1453 DestRect
.left
= XOriginDest
;
1454 DestRect
.top
= YOriginDest
;
1455 DestRect
.right
= XOriginDest
+ WidthDest
;
1456 DestRect
.bottom
= YOriginDest
+ HeightDest
;
1458 SourceRect
.left
= XOriginSrc
;
1459 SourceRect
.top
= YOriginSrc
;
1460 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
1461 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
1463 /* Determine surfaces to be used in the bitblt */
1464 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1465 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1466 BitmapSrc
= BitmapDest
;
1468 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1470 /* Create the XLATEOBJ. */
1471 if (DCDest
->w
.hPalette
!= 0)
1472 DestPalette
= DCDest
->w
.hPalette
;
1473 if (DCSrc
->w
.hPalette
!= 0)
1474 SourcePalette
= DCSrc
->w
.hPalette
;
1476 /* KB41464 details how to convert between mono and color */
1477 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
1483 if (DCDest
->w
.bitsPerPixel
== 1)
1485 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->Dc_Attr
.crBackgroundClr
);
1487 else if (DCSrc
->w
.bitsPerPixel
== 1)
1489 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->Dc_Attr
.crBackgroundClr
, DCSrc
->Dc_Attr
.crForegroundClr
);
1493 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1495 if (NULL
== XlateObj
)
1497 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1498 if (BitmapSrc
!= BitmapDest
)
1499 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1500 DC_UnlockDc(DCDest
);
1501 if (hDCSrc
!= hDCDest
)
1503 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1508 /* Perform the alpha blend operation */
1509 Status
= IntEngAlphaBlend(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1510 DCDest
->CombinedClip
, XlateObj
,
1511 &DestRect
, &SourceRect
, &BlendObj
);
1513 if (XlateObj
!= NULL
)
1514 EngDeleteXlate(XlateObj
);
1516 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1517 if (BitmapSrc
!= BitmapDest
)
1518 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1519 DC_UnlockDc(DCDest
);
1520 if (hDCSrc
!= hDCDest
)
1526 /* Internal Functions */
1529 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1535 return 2 * ((bmWidth
+15) >> 4);
1538 bmWidth
*= 3; /* fall through */
1540 return bmWidth
+ (bmWidth
& 1);
1550 return 2 * ((bmWidth
+3) >> 2);
1559 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1563 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1567 BITMAPOBJ
*Bitmap
, *resBitmap
;
1570 if (hBitmap
== NULL
)
1575 Bitmap
= GDIOBJ_LockObj(GdiHandleTable
, hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1581 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1583 if (Bitmap
->SurfObj
.lDelta
>= 0)
1584 bm
.bmHeight
= -bm
.bmHeight
;
1586 Size
.cx
= abs(bm
.bmWidth
);
1587 Size
.cy
= abs(bm
.bmHeight
);
1588 res
= IntCreateBitmap(Size
,
1590 BitmapFormat(bm
.bmBitsPixel
* bm
.bmPlanes
, BI_RGB
),
1591 (bm
.bmHeight
< 0 ? BMF_TOPDOWN
: 0) | BMF_NOZEROINIT
,
1598 resBitmap
= GDIOBJ_LockObj(GdiHandleTable
, res
, GDI_OBJECT_TYPE_BITMAP
);
1601 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1602 IntGetBitmapBits (Bitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1603 IntSetBitmapBits (resBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1605 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, resBitmap
);
1609 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, Bitmap
);
1615 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT Count
, LPVOID buffer
)
1617 if ((UINT
)Count
< sizeof(BITMAP
)) return 0;
1621 if((UINT
)Count
< sizeof(DIBSECTION
))
1623 Count
= sizeof(BITMAP
);
1627 Count
= sizeof(DIBSECTION
);
1631 memcpy(buffer
, bmp
->dib
, Count
);
1637 Count
= sizeof(BITMAP
);
1642 Count
= sizeof(BITMAP
);
1644 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1645 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1646 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1647 Bitmap
.bmPlanes
= 1;
1648 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1649 //Bitmap.bmBits = bmp->SurfObj.pvBits;
1650 Bitmap
.bmBits
= NULL
; /* not set accoring wine test confirm in win2k */
1651 memcpy(buffer
, &Bitmap
, Count
);