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
->w
.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
->w
.backgroundColor
);
190 else if (DCSrc
->w
.bitsPerPixel
== 1)
192 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
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
);
404 IntCreateBitmapIndirect(CONST BITMAP
*BM
)
411 /* NOTE: Windows also doesn't store nr. of planes separately! */
412 BitsPixel
= BM
->bmBitsPixel
* BM
->bmPlanes
;
414 /* Check parameters */
415 if (0 == BM
->bmHeight
|| 0 == BM
->bmWidth
)
417 Size
.cx
= Size
.cy
= 1;
421 Size
.cx
= abs(BM
->bmWidth
);
422 Size
.cy
= abs(BM
->bmHeight
);
425 /* Create the bitmap object. */
426 hBitmap
= IntCreateBitmap(Size
, BM
->bmWidthBytes
,
427 BitmapFormat(BitsPixel
, BI_RGB
),
428 (BM
->bmHeight
< 0 ? BMF_TOPDOWN
: 0) |
429 (NULL
== BM
->bmBits
? 0 : BMF_NOZEROINIT
), NULL
);
432 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
436 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
437 Size
.cx
, Size
.cy
, BitsPixel
, hBitmap
);
439 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
442 /* FIXME should we free the hBitmap or return it ?? */
446 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
447 BITMAPOBJ_UnlockBitmap( bmp
);
450 * NOTE: It's ugly practice, but we are using the object even
451 * after unlocking. Since the handle is currently known only
452 * to us it should be safe.
455 if (NULL
!= BM
->bmBits
)
457 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, BM
->bmBits
);
469 IN OPTIONAL LPBYTE Bits
)
475 BM
.bmHeight
= Height
;
476 BM
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes(Width
, Planes
* BitsPixel
);
477 BM
.bmPlanes
= Planes
;
478 BM
.bmBitsPixel
= BitsPixel
;
481 return IntCreateBitmapIndirect(&BM
);
485 BITMAP_Cleanup(PVOID ObjectBody
)
487 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
488 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
489 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
491 if (pBmp
->dib
== NULL
)
493 if (pBmp
->SurfObj
.pvBits
!= NULL
)
494 ExFreePool(pBmp
->SurfObj
.pvBits
);
498 if (pBmp
->SurfObj
.pvBits
!= NULL
)
499 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
501 if (pBmp
->hDIBPalette
!= NULL
)
503 NtGdiDeleteObject(pBmp
->hDIBPalette
);
507 if (NULL
!= pBmp
->BitsLock
)
509 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
510 pBmp
->BitsLock
= NULL
;
518 IntCreateCompatibleBitmap(
527 if ((Width
>= 0x10000) || (Height
>= 0x10000))
529 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
533 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
534 if (0 == Width
|| 0 == Height
)
536 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
540 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
547 NtGdiCreateCompatibleBitmap(
557 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
561 SetLastWin32Error(ERROR_INVALID_HANDLE
);
565 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
567 DPRINT ("\t\t%04x\n", Bmp
);
573 NtGdiCreateBitmapIndirect(CONST BITMAP
*UnsafeBM
)
576 NTSTATUS Status
= STATUS_SUCCESS
;
580 ProbeForRead(UnsafeBM
, sizeof(BITMAP
), 1);
582 if (NULL
!= BM
.bmBits
)
584 ProbeForRead(BM
.bmBits
, BM
.bmWidthBytes
* abs(BM
.bmHeight
), 2);
589 Status
= _SEH_GetExceptionCode();
592 if(!NT_SUCCESS(Status
))
594 SetLastNtError(Status
);
598 return IntCreateBitmapIndirect(&BM
);
602 NtGdiCreateDiscardableBitmap(
607 /* FIXME: this probably should do something else */
608 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
619 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
621 /* lie and say we succeded */
632 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
636 NtGdiGetBitmapDimensionEx(
642 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
648 *Dimension
= bmp
->dimension
;
650 BITMAPOBJ_UnlockBitmap(bmp
);
656 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
659 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
660 BOOL bInRect
= FALSE
;
661 BITMAPOBJ
*BitmapObject
;
662 SURFOBJ
*SurfaceObject
;
667 dc
= DC_LockDc (hDC
);
671 SetLastWin32Error(ERROR_INVALID_HANDLE
);
679 XPos
+= dc
->w
.DCOrgX
;
680 YPos
+= dc
->w
.DCOrgY
;
681 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
684 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
685 SurfaceObject
= &BitmapObject
->SurfObj
;
688 if ( dc
->w
.hPalette
!= 0 )
689 Pal
= dc
->w
.hPalette
;
690 /* FIXME: Verify if it shouldn't be PAL_BGR! */
691 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
694 // check if this DC has a DIB behind it...
695 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
697 ASSERT ( SurfaceObject
->lDelta
);
698 Result
= XLATEOBJ_iXlate(XlateObj
,
699 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
701 EngDeleteXlate(XlateObj
);
703 BITMAPOBJ_UnlockBitmap(BitmapObject
);
708 // if Result is still CLR_INVALID, then the "quick" method above didn't work
709 if ( bInRect
&& Result
== CLR_INVALID
)
711 // FIXME: create a 1x1 32BPP DIB, and blit to it
712 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
715 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
717 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
718 hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
719 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
722 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
727 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
, 0, 0 );
728 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
730 // our bitmap is no longer selected, so we can access it's stuff...
731 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
734 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
735 BITMAPOBJ_UnlockBitmap ( bmpobj
);
738 NtGdiDeleteObject ( hBmpTmp
);
740 NtGdiDeleteObjectApp ( hDCTmp
);
747 /***********************************************************************
749 * Ported from WINE by sedwards 11-4-03
751 * Someone thought it would be faster to do it here and then switch back
752 * to GDI32. I dunno. Write a test and let me know.
756 SwapROP3_SrcDst(BYTE bRop3
)
758 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
761 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
762 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
763 #define DSTCOPY 0x00AA0029
764 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
768 HDC hdcDest
, INT nXDest
, INT nYDest
,
769 INT nWidth
, INT nHeight
, HDC hdcSrc
,
770 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
771 INT xMask
, INT yMask
, DWORD dwRop
,
772 IN DWORD crBackColor
)
774 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
775 HDC hDCMask
, hDC1
, hDC2
;
776 static const DWORD ROP3Table
[256] =
778 0x00000042, 0x00010289,
779 0x00020C89, 0x000300AA,
780 0x00040C88, 0x000500A9,
781 0x00060865, 0x000702C5,
782 0x00080F08, 0x00090245,
783 0x000A0329, 0x000B0B2A,
784 0x000C0324, 0x000D0B25,
785 0x000E08A5, 0x000F0001,
786 0x00100C85, 0x001100A6,
787 0x00120868, 0x001302C8,
788 0x00140869, 0x001502C9,
789 0x00165CCA, 0x00171D54,
790 0x00180D59, 0x00191CC8,
791 0x001A06C5, 0x001B0768,
792 0x001C06CA, 0x001D0766,
793 0x001E01A5, 0x001F0385,
794 0x00200F09, 0x00210248,
795 0x00220326, 0x00230B24,
796 0x00240D55, 0x00251CC5,
797 0x002606C8, 0x00271868,
798 0x00280369, 0x002916CA,
799 0x002A0CC9, 0x002B1D58,
800 0x002C0784, 0x002D060A,
801 0x002E064A, 0x002F0E2A,
802 0x0030032A, 0x00310B28,
803 0x00320688, 0x00330008,
804 0x003406C4, 0x00351864,
805 0x003601A8, 0x00370388,
806 0x0038078A, 0x00390604,
807 0x003A0644, 0x003B0E24,
808 0x003C004A, 0x003D18A4,
809 0x003E1B24, 0x003F00EA,
810 0x00400F0A, 0x00410249,
811 0x00420D5D, 0x00431CC4,
812 0x00440328, 0x00450B29,
813 0x004606C6, 0x0047076A,
814 0x00480368, 0x004916C5,
815 0x004A0789, 0x004B0605,
816 0x004C0CC8, 0x004D1954,
817 0x004E0645, 0x004F0E25,
818 0x00500325, 0x00510B26,
819 0x005206C9, 0x00530764,
820 0x005408A9, 0x00550009,
821 0x005601A9, 0x00570389,
822 0x00580785, 0x00590609,
823 0x005A0049, 0x005B18A9,
824 0x005C0649, 0x005D0E29,
825 0x005E1B29, 0x005F00E9,
826 0x00600365, 0x006116C6,
827 0x00620786, 0x00630608,
828 0x00640788, 0x00650606,
829 0x00660046, 0x006718A8,
830 0x006858A6, 0x00690145,
831 0x006A01E9, 0x006B178A,
832 0x006C01E8, 0x006D1785,
833 0x006E1E28, 0x006F0C65,
834 0x00700CC5, 0x00711D5C,
835 0x00720648, 0x00730E28,
836 0x00740646, 0x00750E26,
837 0x00761B28, 0x007700E6,
838 0x007801E5, 0x00791786,
839 0x007A1E29, 0x007B0C68,
840 0x007C1E24, 0x007D0C69,
841 0x007E0955, 0x007F03C9,
842 0x008003E9, 0x00810975,
843 0x00820C49, 0x00831E04,
844 0x00840C48, 0x00851E05,
845 0x008617A6, 0x008701C5,
846 0x008800C6, 0x00891B08,
847 0x008A0E06, 0x008B0666,
848 0x008C0E08, 0x008D0668,
849 0x008E1D7C, 0x008F0CE5,
850 0x00900C45, 0x00911E08,
851 0x009217A9, 0x009301C4,
852 0x009417AA, 0x009501C9,
853 0x00960169, 0x0097588A,
854 0x00981888, 0x00990066,
855 0x009A0709, 0x009B07A8,
856 0x009C0704, 0x009D07A6,
857 0x009E16E6, 0x009F0345,
858 0x00A000C9, 0x00A11B05,
859 0x00A20E09, 0x00A30669,
860 0x00A41885, 0x00A50065,
861 0x00A60706, 0x00A707A5,
862 0x00A803A9, 0x00A90189,
863 0x00AA0029, 0x00AB0889,
864 0x00AC0744, 0x00AD06E9,
865 0x00AE0B06, 0x00AF0229,
866 0x00B00E05, 0x00B10665,
867 0x00B21974, 0x00B30CE8,
868 0x00B4070A, 0x00B507A9,
869 0x00B616E9, 0x00B70348,
870 0x00B8074A, 0x00B906E6,
871 0x00BA0B09, 0x00BB0226,
872 0x00BC1CE4, 0x00BD0D7D,
873 0x00BE0269, 0x00BF08C9,
874 0x00C000CA, 0x00C11B04,
875 0x00C21884, 0x00C3006A,
876 0x00C40E04, 0x00C50664,
877 0x00C60708, 0x00C707AA,
878 0x00C803A8, 0x00C90184,
879 0x00CA0749, 0x00CB06E4,
880 0x00CC0020, 0x00CD0888,
881 0x00CE0B08, 0x00CF0224,
882 0x00D00E0A, 0x00D1066A,
883 0x00D20705, 0x00D307A4,
884 0x00D41D78, 0x00D50CE9,
885 0x00D616EA, 0x00D70349,
886 0x00D80745, 0x00D906E8,
887 0x00DA1CE9, 0x00DB0D75,
888 0x00DC0B04, 0x00DD0228,
889 0x00DE0268, 0x00DF08C8,
890 0x00E003A5, 0x00E10185,
891 0x00E20746, 0x00E306EA,
892 0x00E40748, 0x00E506E5,
893 0x00E61CE8, 0x00E70D79,
894 0x00E81D74, 0x00E95CE6,
895 0x00EA02E9, 0x00EB0849,
896 0x00EC02E8, 0x00ED0848,
897 0x00EE0086, 0x00EF0A08,
898 0x00F00021, 0x00F10885,
899 0x00F20B05, 0x00F3022A,
900 0x00F40B0A, 0x00F50225,
901 0x00F60265, 0x00F708C5,
902 0x00F802E5, 0x00F90845,
903 0x00FA0089, 0x00FB0A09,
904 0x00FC008A, 0x00FD0A0A,
905 0x00FE02A9, 0x00FF0062,
909 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0);
911 /* 1. make mask bitmap's dc */
912 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
913 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
915 /* 2. make masked Background bitmap */
917 /* 2.1 make bitmap */
918 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
919 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
920 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
922 /* 2.2 draw dest bitmap and mask */
923 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
924 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
925 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
, 0, 0);
927 /* 3. make masked Foreground bitmap */
929 /* 3.1 make bitmap */
930 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
931 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
932 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
934 /* 3.2 draw src bitmap and mask */
935 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
936 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
937 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
, 0, 0);
939 /* 4. combine two bitmap and copy it to hdcDest */
940 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
, 0, 0);
941 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
, 0, 0);
943 /* 5. restore all object */
944 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
945 NtGdiSelectObject(hDC1
, hOldBitmap2
);
946 NtGdiSelectObject(hDC2
, hOldBitmap3
);
948 /* 6. delete all temp object */
949 NtGdiDeleteObject(hBitmap2
);
950 NtGdiDeleteObject(hBitmap3
);
952 NtGdiDeleteObjectApp(hDC1
);
953 NtGdiDeleteObjectApp(hDC2
);
954 NtGdiDeleteObjectApp(hDCMask
);
972 IN DWORD crBackColor
)
987 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
988 if (bmp
== NULL
|| Bits
== NULL
)
995 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
999 /* Only get entire lines */
1000 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
1001 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
1003 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
1005 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
1006 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
1010 bmp
->SurfObj
.sizlBitmap
.cx
,
1011 bmp
->SurfObj
.sizlBitmap
.cy
,
1012 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
1016 /* FIXME: call DDI specific function here if available */
1019 DPRINT ("Calling device specific BitmapBits\n");
1020 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
1022 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
1026 DPRINT ("BitmapBits == NULL??\n");
1033 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
1037 BITMAPOBJ_UnlockBitmap(bmp
);
1043 NtGdiSetBitmapDimensionEx(
1051 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1059 *Size
= bmp
->dimension
;
1061 bmp
->dimension
.cx
= Width
;
1062 bmp
->dimension
.cy
= Height
;
1064 BITMAPOBJ_UnlockBitmap (bmp
);
1077 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1080 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1082 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1084 Color
= NtGdiGetPixel(hDC
,X
,Y
);
1085 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1089 Color
= ((COLORREF
) -1);
1090 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X
,Y
,Color
);
1101 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
, NULL
);
1104 if (NewBrush
== NULL
)
1106 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1107 if (OldBrush
== NULL
)
1109 NtGdiDeleteObject(NewBrush
);
1112 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1113 NtGdiSelectObject(hDC
, OldBrush
);
1114 NtGdiDeleteObject(NewBrush
);
1131 IN DWORD dwBackColor
)
1135 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1139 XLATEOBJ
*XlateObj
= NULL
;
1140 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1141 PGDIBRUSHOBJ BrushObj
;
1142 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1143 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1145 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1147 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1150 DCDest
= DC_LockDc(hDCDest
);
1153 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1154 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1159 DC_UnlockDc(DCDest
);
1160 /* Yes, Windows really returns TRUE in this case */
1166 if (hDCSrc
!= hDCDest
)
1168 DCSrc
= DC_LockDc(hDCSrc
);
1171 DC_UnlockDc(DCDest
);
1172 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1173 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1179 DC_UnlockDc(DCDest
);
1180 /* Yes, Windows really returns TRUE in this case */
1194 /* Offset the destination and source by the origin of their DCs. */
1195 XOriginDest
+= DCDest
->w
.DCOrgX
;
1196 YOriginDest
+= DCDest
->w
.DCOrgY
;
1199 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1200 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1203 DestRect
.left
= XOriginDest
;
1204 DestRect
.top
= YOriginDest
;
1205 DestRect
.right
= XOriginDest
+WidthDest
;
1206 DestRect
.bottom
= YOriginDest
+HeightDest
;
1208 SourceRect
.left
= XOriginSrc
;
1209 SourceRect
.top
= YOriginSrc
;
1210 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1211 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1213 /* Determine surfaces to be used in the bitblt */
1214 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1217 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1218 BitmapSrc
= BitmapDest
;
1220 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1229 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1230 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1231 if ( SourceRect
.left
< 0 )
1233 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1234 SourceRect
.left
= 0;
1236 if ( SourceRect
.top
< 0 )
1238 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1241 if ( SourceRect
.right
< -1 )
1243 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1244 SourceRect
.right
= -1;
1246 if ( SourceRect
.bottom
< -1 )
1248 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1249 SourceRect
.bottom
= -1;
1251 if ( SourceRect
.right
> sw
)
1253 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1254 SourceRect
.right
= sw
;
1256 if ( SourceRect
.bottom
> sh
)
1258 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1259 SourceRect
.bottom
= sh
;
1263 if ( SourceRect
.left
> sw
)
1265 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1266 SourceRect
.left
= 0;
1268 if ( SourceRect
.top
> sh
)
1270 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1273 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1275 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1283 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1284 if (NULL
== BrushObj
)
1286 if (UsesSource
&& hDCSrc
!= hDCDest
)
1290 DC_UnlockDc(DCDest
);
1291 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1300 /* Create the XLATEOBJ. */
1303 if (DCDest
->w
.hPalette
!= 0)
1304 DestPalette
= DCDest
->w
.hPalette
;
1306 if (DCSrc
->w
.hPalette
!= 0)
1307 SourcePalette
= DCSrc
->w
.hPalette
;
1309 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1310 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1311 if (NULL
== XlateObj
)
1313 if (UsesSource
&& hDCSrc
!= hDCDest
)
1317 DC_UnlockDc(DCDest
);
1318 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1323 /* Perform the bitblt operation */
1324 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1325 NULL
, DCDest
->CombinedClip
, XlateObj
,
1326 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1330 EngDeleteXlate(XlateObj
);
1333 BRUSHOBJ_UnlockBrush(BrushObj
);
1336 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1338 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1340 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1341 if (UsesSource
&& hDCSrc
!= hDCDest
)
1345 DC_UnlockDc(DCDest
);
1362 BLENDFUNCTION BlendFunc
)
1366 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1367 RECTL DestRect
, SourceRect
;
1371 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1372 BlendObj
.BlendFunction
= BlendFunc
;
1374 DCDest
= DC_LockDc(hDCDest
);
1377 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
);
1378 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1383 DC_UnlockDc(DCDest
);
1384 /* Yes, Windows really returns TRUE in this case */
1388 if (hDCSrc
!= hDCDest
)
1390 DCSrc
= DC_LockDc(hDCSrc
);
1393 DC_UnlockDc(DCDest
);
1394 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc
);
1395 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1401 DC_UnlockDc(DCDest
);
1402 /* Yes, Windows really returns TRUE in this case */
1411 /* Offset the destination and source by the origin of their DCs. */
1412 XOriginDest
+= DCDest
->w
.DCOrgX
;
1413 YOriginDest
+= DCDest
->w
.DCOrgY
;
1414 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1415 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1417 DestRect
.left
= XOriginDest
;
1418 DestRect
.top
= YOriginDest
;
1419 DestRect
.right
= XOriginDest
+ WidthDest
;
1420 DestRect
.bottom
= YOriginDest
+ HeightDest
;
1422 SourceRect
.left
= XOriginSrc
;
1423 SourceRect
.top
= YOriginSrc
;
1424 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
1425 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
1427 /* Determine surfaces to be used in the bitblt */
1428 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1429 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1430 BitmapSrc
= BitmapDest
;
1432 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1434 /* Create the XLATEOBJ. */
1435 if (DCDest
->w
.hPalette
!= 0)
1436 DestPalette
= DCDest
->w
.hPalette
;
1437 if (DCSrc
->w
.hPalette
!= 0)
1438 SourcePalette
= DCSrc
->w
.hPalette
;
1440 /* KB41464 details how to convert between mono and color */
1441 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
1447 if (DCDest
->w
.bitsPerPixel
== 1)
1449 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
1451 else if (DCSrc
->w
.bitsPerPixel
== 1)
1453 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
1457 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1459 if (NULL
== XlateObj
)
1461 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1462 if (BitmapSrc
!= BitmapDest
)
1463 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1464 DC_UnlockDc(DCDest
);
1465 if (hDCSrc
!= hDCDest
)
1467 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1472 /* Perform the alpha blend operation */
1473 Status
= IntEngAlphaBlend(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1474 DCDest
->CombinedClip
, XlateObj
,
1475 &DestRect
, &SourceRect
, &BlendObj
);
1477 if (XlateObj
!= NULL
)
1478 EngDeleteXlate(XlateObj
);
1480 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1481 if (BitmapSrc
!= BitmapDest
)
1482 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1483 DC_UnlockDc(DCDest
);
1484 if (hDCSrc
!= hDCDest
)
1490 /* Internal Functions */
1493 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1499 return 2 * ((bmWidth
+15) >> 4);
1502 bmWidth
*= 3; /* fall through */
1504 return bmWidth
+ (bmWidth
& 1);
1514 return 2 * ((bmWidth
+3) >> 2);
1523 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1527 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1533 if (hBitmap
== NULL
)
1538 Bitmap
= GDIOBJ_LockObj(GdiHandleTable
, hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1544 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1546 if (Bitmap
->SurfObj
.lDelta
>= 0)
1547 bm
.bmHeight
= -bm
.bmHeight
;
1549 res
= IntCreateBitmapIndirect(&bm
);
1554 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1555 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1556 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1560 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, Bitmap
);
1566 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT Count
, LPVOID buffer
)
1568 if ((UINT
)Count
< sizeof(BITMAP
)) return 0;
1569 if( buffer
== NULL
)
1571 if ((UINT
)Count
< sizeof(DIBSECTION
))
1573 return sizeof(BITMAP
);
1575 return sizeof(DIBSECTION
);
1580 if((UINT
)Count
< sizeof(DIBSECTION
))
1582 Count
= sizeof(BITMAP
);
1586 Count
= sizeof(DIBSECTION
);
1588 memcpy(buffer
, bmp
->dib
, Count
);
1595 Count
= sizeof(BITMAP
);
1597 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1598 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1599 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1600 Bitmap
.bmPlanes
= 1;
1601 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1602 //Bitmap.bmBits = bmp->SurfObj.pvBits;
1603 Bitmap
.bmBits
= NULL
; /* not set accoring wine test confirm in win2k */
1604 memcpy(buffer
, &Bitmap
, Count
);