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 SourcePoint
.x
= XSrc
;
120 SourcePoint
.y
= YSrc
;
125 /* Determine surfaces to be used in the bitblt */
126 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
129 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
130 BitmapSrc
= BitmapDest
;
132 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
141 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
142 if (NULL
== BrushObj
)
144 if (UsesSource
&& hDCSrc
!= hDCDest
)
148 if(BitmapDest
!= NULL
)
150 BITMAPOBJ_UnlockBitmap(BitmapDest
);
152 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
154 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
157 SetLastWin32Error(ERROR_INVALID_HANDLE
);
160 BrushOrigin
= BrushObj
->ptOrigin
;
161 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
168 /* Create the XLATEOBJ. */
171 if (DCDest
->w
.hPalette
!= 0)
172 DestPalette
= DCDest
->w
.hPalette
;
174 if (DCSrc
->w
.hPalette
!= 0)
175 SourcePalette
= DCSrc
->w
.hPalette
;
177 /* KB41464 details how to convert between mono and color */
178 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
184 if (DCDest
->w
.bitsPerPixel
== 1)
186 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
188 else if (DCSrc
->w
.bitsPerPixel
== 1)
190 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
194 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
196 if (NULL
== XlateObj
)
198 if (UsesSource
&& hDCSrc
!= hDCDest
)
203 if(BitmapDest
!= NULL
)
205 BITMAPOBJ_UnlockBitmap(BitmapDest
);
207 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
209 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
213 BRUSHOBJ_UnlockBrush(BrushObj
);
215 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
221 /* Perform the bitblt operation */
222 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
, NULL
,
223 DCDest
->CombinedClip
, XlateObj
, &DestRect
,
225 BrushObj
? &BrushInst
.BrushObject
: NULL
,
226 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
228 if (UsesSource
&& XlateObj
!= NULL
)
229 EngDeleteXlate(XlateObj
);
231 if(BitmapDest
!= NULL
)
233 BITMAPOBJ_UnlockBitmap(BitmapDest
);
235 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
237 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
239 if (BrushObj
!= NULL
)
241 BRUSHOBJ_UnlockBrush(BrushObj
);
243 if (UsesSource
&& hDCSrc
!= hDCDest
)
268 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
270 HPALETTE SourcePalette
= 0, DestPalette
= 0;
271 PPALGDI PalDestGDI
, PalSourceGDI
;
272 USHORT PalDestMode
, PalSrcMode
;
273 ULONG TransparentColor
= 0;
276 if(!(DCDest
= DC_LockDc(hdcDst
)))
278 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
279 SetLastWin32Error(ERROR_INVALID_HANDLE
);
285 /* Yes, Windows really returns TRUE in this case */
289 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
292 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
293 SetLastWin32Error(ERROR_INVALID_HANDLE
);
307 /* Yes, Windows really returns TRUE in this case */
311 /* Offset positions */
312 xDst
+= DCDest
->w
.DCOrgX
;
313 yDst
+= DCDest
->w
.DCOrgY
;
314 xSrc
+= DCSrc
->w
.DCOrgX
;
315 ySrc
+= DCSrc
->w
.DCOrgY
;
317 if(DCDest
->w
.hPalette
)
318 DestPalette
= DCDest
->w
.hPalette
;
320 if(DCSrc
->w
.hPalette
)
321 SourcePalette
= DCSrc
->w
.hPalette
;
323 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
327 SetLastWin32Error(ERROR_INVALID_HANDLE
);
330 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
332 PALETTE_UnlockPalette(PalSourceGDI
);
335 SetLastWin32Error(ERROR_INVALID_HANDLE
);
338 if(DestPalette
!= SourcePalette
)
340 PalDestMode
= PalDestGDI
->Mode
;
341 PalSrcMode
= PalSourceGDI
->Mode
;
342 PALETTE_UnlockPalette(PalDestGDI
);
346 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
348 PALETTE_UnlockPalette(PalSourceGDI
);
350 /* Translate Transparent (RGB) Color to the source palette */
351 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
353 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
354 EngDeleteXlate(XlateObj
);
357 /* Create the XLATE object to convert colors between source and destination */
358 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
360 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
361 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
363 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
364 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
369 rcDest
.right
= rcDest
.left
+ cxDst
;
370 rcDest
.bottom
= rcDest
.top
+ cyDst
;
373 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
374 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
376 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
378 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
382 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
383 DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
384 TransparentColor
, 0);
387 BITMAPOBJ_UnlockBitmap(BitmapDest
);
388 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
396 EngDeleteXlate(XlateObj
);
401 static FASTCALL HBITMAP
402 IntCreateBitmapIndirect(CONST BITMAP
*BM
)
409 /* NOTE: Windows also doesn't store nr. of planes separately! */
410 BitsPixel
= BM
->bmBitsPixel
* BM
->bmPlanes
;
412 /* Check parameters */
413 if (0 == BM
->bmHeight
|| 0 == BM
->bmWidth
)
415 Size
.cx
= Size
.cy
= 1;
419 Size
.cx
= abs(BM
->bmWidth
);
420 Size
.cy
= abs(BM
->bmHeight
);
423 /* Create the bitmap object. */
424 hBitmap
= IntCreateBitmap(Size
, BM
->bmWidthBytes
,
425 BitmapFormat(BitsPixel
, BI_RGB
),
426 (BM
->bmHeight
< 0 ? BMF_TOPDOWN
: 0) |
427 (NULL
== BM
->bmBits
? 0 : BMF_NOZEROINIT
), NULL
);
430 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
434 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
435 Size
.cx
, Size
.cy
, BitsPixel
, hBitmap
);
437 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
438 /* FIXME - bmp can be NULL!!!!!! */
439 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
440 BITMAPOBJ_UnlockBitmap( bmp
);
443 * NOTE: It's ugly practice, but we are using the object even
444 * after unlocking. Since the handle is currently known only
445 * to us it should be safe.
448 if (NULL
!= BM
->bmBits
)
450 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, BM
->bmBits
);
462 IN OPTIONAL LPBYTE Bits
)
468 BM
.bmHeight
= Height
;
469 BM
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes(Width
, Planes
* BitsPixel
);
470 BM
.bmPlanes
= Planes
;
471 BM
.bmBitsPixel
= BitsPixel
;
474 return IntCreateBitmapIndirect(&BM
);
478 BITMAP_Cleanup(PVOID ObjectBody
)
480 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
481 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
482 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
484 if (pBmp
->dib
== NULL
)
486 ExFreePool(pBmp
->SurfObj
.pvBits
);
490 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
492 if (pBmp
->hDIBPalette
)
494 NtGdiDeleteObject(pBmp
->hDIBPalette
);
498 if (NULL
!= pBmp
->BitsLock
)
500 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
501 pBmp
->BitsLock
= NULL
;
509 IntCreateCompatibleBitmap(
518 if ((Width
>= 0x10000) || (Height
>= 0x10000))
520 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
524 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
525 if (0 == Width
|| 0 == Height
)
527 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
531 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
538 NtGdiCreateCompatibleBitmap(
548 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
552 SetLastWin32Error(ERROR_INVALID_HANDLE
);
556 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
558 DPRINT ("\t\t%04x\n", Bmp
);
564 NtGdiCreateBitmapIndirect(CONST BITMAP
*UnsafeBM
)
567 NTSTATUS Status
= STATUS_SUCCESS
;
571 ProbeForRead(UnsafeBM
, sizeof(BITMAP
), 1);
573 if (NULL
!= BM
.bmBits
)
575 ProbeForRead(BM
.bmBits
, BM
.bmWidthBytes
* abs(BM
.bmHeight
), 2);
580 Status
= _SEH_GetExceptionCode();
583 if(!NT_SUCCESS(Status
))
585 SetLastNtError(Status
);
589 return IntCreateBitmapIndirect(&BM
);
593 NtGdiCreateDiscardableBitmap(
598 /* FIXME: this probably should do something else */
599 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
610 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
612 /* lie and say we succeded */
623 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
627 NtGdiGetBitmapDimensionEx(
633 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
639 *Dimension
= bmp
->dimension
;
641 BITMAPOBJ_UnlockBitmap(bmp
);
647 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
650 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
651 BOOL bInRect
= FALSE
;
652 BITMAPOBJ
*BitmapObject
;
653 SURFOBJ
*SurfaceObject
;
657 dc
= DC_LockDc (hDC
);
661 SetLastWin32Error(ERROR_INVALID_HANDLE
);
669 XPos
+= dc
->w
.DCOrgX
;
670 YPos
+= dc
->w
.DCOrgY
;
671 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
674 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
675 SurfaceObject
= &BitmapObject
->SurfObj
;
678 if ( dc
->w
.hPalette
!= 0 )
679 Pal
= dc
->w
.hPalette
;
680 /* FIXME: Verify if it shouldn't be PAL_BGR! */
681 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
684 // check if this DC has a DIB behind it...
685 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
687 ASSERT ( SurfaceObject
->lDelta
);
688 Result
= XLATEOBJ_iXlate(XlateObj
,
689 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
691 EngDeleteXlate(XlateObj
);
693 BITMAPOBJ_UnlockBitmap(BitmapObject
);
698 // if Result is still CLR_INVALID, then the "quick" method above didn't work
699 if ( bInRect
&& Result
== CLR_INVALID
)
701 // FIXME: create a 1x1 32BPP DIB, and blit to it
702 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
705 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
707 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
708 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
709 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
712 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
717 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
, 0, 0 );
718 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
720 // our bitmap is no longer selected, so we can access it's stuff...
721 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
724 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
725 BITMAPOBJ_UnlockBitmap ( bmpobj
);
728 NtGdiDeleteObject ( hBmpTmp
);
730 NtGdiDeleteDC ( hDCTmp
);
737 /***********************************************************************
739 * Ported from WINE by sedwards 11-4-03
741 * Someone thought it would be faster to do it here and then switch back
742 * to GDI32. I dunno. Write a test and let me know.
746 SwapROP3_SrcDst(BYTE bRop3
)
748 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
751 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
752 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
753 #define DSTCOPY 0x00AA0029
754 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
758 HDC hdcDest
, INT nXDest
, INT nYDest
,
759 INT nWidth
, INT nHeight
, HDC hdcSrc
,
760 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
761 INT xMask
, INT yMask
, DWORD dwRop
,
762 IN DWORD crBackColor
)
764 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
765 HDC hDCMask
, hDC1
, hDC2
;
766 static const DWORD ROP3Table
[256] =
768 0x00000042, 0x00010289,
769 0x00020C89, 0x000300AA,
770 0x00040C88, 0x000500A9,
771 0x00060865, 0x000702C5,
772 0x00080F08, 0x00090245,
773 0x000A0329, 0x000B0B2A,
774 0x000C0324, 0x000D0B25,
775 0x000E08A5, 0x000F0001,
776 0x00100C85, 0x001100A6,
777 0x00120868, 0x001302C8,
778 0x00140869, 0x001502C9,
779 0x00165CCA, 0x00171D54,
780 0x00180D59, 0x00191CC8,
781 0x001A06C5, 0x001B0768,
782 0x001C06CA, 0x001D0766,
783 0x001E01A5, 0x001F0385,
784 0x00200F09, 0x00210248,
785 0x00220326, 0x00230B24,
786 0x00240D55, 0x00251CC5,
787 0x002606C8, 0x00271868,
788 0x00280369, 0x002916CA,
789 0x002A0CC9, 0x002B1D58,
790 0x002C0784, 0x002D060A,
791 0x002E064A, 0x002F0E2A,
792 0x0030032A, 0x00310B28,
793 0x00320688, 0x00330008,
794 0x003406C4, 0x00351864,
795 0x003601A8, 0x00370388,
796 0x0038078A, 0x00390604,
797 0x003A0644, 0x003B0E24,
798 0x003C004A, 0x003D18A4,
799 0x003E1B24, 0x003F00EA,
800 0x00400F0A, 0x00410249,
801 0x00420D5D, 0x00431CC4,
802 0x00440328, 0x00450B29,
803 0x004606C6, 0x0047076A,
804 0x00480368, 0x004916C5,
805 0x004A0789, 0x004B0605,
806 0x004C0CC8, 0x004D1954,
807 0x004E0645, 0x004F0E25,
808 0x00500325, 0x00510B26,
809 0x005206C9, 0x00530764,
810 0x005408A9, 0x00550009,
811 0x005601A9, 0x00570389,
812 0x00580785, 0x00590609,
813 0x005A0049, 0x005B18A9,
814 0x005C0649, 0x005D0E29,
815 0x005E1B29, 0x005F00E9,
816 0x00600365, 0x006116C6,
817 0x00620786, 0x00630608,
818 0x00640788, 0x00650606,
819 0x00660046, 0x006718A8,
820 0x006858A6, 0x00690145,
821 0x006A01E9, 0x006B178A,
822 0x006C01E8, 0x006D1785,
823 0x006E1E28, 0x006F0C65,
824 0x00700CC5, 0x00711D5C,
825 0x00720648, 0x00730E28,
826 0x00740646, 0x00750E26,
827 0x00761B28, 0x007700E6,
828 0x007801E5, 0x00791786,
829 0x007A1E29, 0x007B0C68,
830 0x007C1E24, 0x007D0C69,
831 0x007E0955, 0x007F03C9,
832 0x008003E9, 0x00810975,
833 0x00820C49, 0x00831E04,
834 0x00840C48, 0x00851E05,
835 0x008617A6, 0x008701C5,
836 0x008800C6, 0x00891B08,
837 0x008A0E06, 0x008B0666,
838 0x008C0E08, 0x008D0668,
839 0x008E1D7C, 0x008F0CE5,
840 0x00900C45, 0x00911E08,
841 0x009217A9, 0x009301C4,
842 0x009417AA, 0x009501C9,
843 0x00960169, 0x0097588A,
844 0x00981888, 0x00990066,
845 0x009A0709, 0x009B07A8,
846 0x009C0704, 0x009D07A6,
847 0x009E16E6, 0x009F0345,
848 0x00A000C9, 0x00A11B05,
849 0x00A20E09, 0x00A30669,
850 0x00A41885, 0x00A50065,
851 0x00A60706, 0x00A707A5,
852 0x00A803A9, 0x00A90189,
853 0x00AA0029, 0x00AB0889,
854 0x00AC0744, 0x00AD06E9,
855 0x00AE0B06, 0x00AF0229,
856 0x00B00E05, 0x00B10665,
857 0x00B21974, 0x00B30CE8,
858 0x00B4070A, 0x00B507A9,
859 0x00B616E9, 0x00B70348,
860 0x00B8074A, 0x00B906E6,
861 0x00BA0B09, 0x00BB0226,
862 0x00BC1CE4, 0x00BD0D7D,
863 0x00BE0269, 0x00BF08C9,
864 0x00C000CA, 0x00C11B04,
865 0x00C21884, 0x00C3006A,
866 0x00C40E04, 0x00C50664,
867 0x00C60708, 0x00C707AA,
868 0x00C803A8, 0x00C90184,
869 0x00CA0749, 0x00CB06E4,
870 0x00CC0020, 0x00CD0888,
871 0x00CE0B08, 0x00CF0224,
872 0x00D00E0A, 0x00D1066A,
873 0x00D20705, 0x00D307A4,
874 0x00D41D78, 0x00D50CE9,
875 0x00D616EA, 0x00D70349,
876 0x00D80745, 0x00D906E8,
877 0x00DA1CE9, 0x00DB0D75,
878 0x00DC0B04, 0x00DD0228,
879 0x00DE0268, 0x00DF08C8,
880 0x00E003A5, 0x00E10185,
881 0x00E20746, 0x00E306EA,
882 0x00E40748, 0x00E506E5,
883 0x00E61CE8, 0x00E70D79,
884 0x00E81D74, 0x00E95CE6,
885 0x00EA02E9, 0x00EB0849,
886 0x00EC02E8, 0x00ED0848,
887 0x00EE0086, 0x00EF0A08,
888 0x00F00021, 0x00F10885,
889 0x00F20B05, 0x00F3022A,
890 0x00F40B0A, 0x00F50225,
891 0x00F60265, 0x00F708C5,
892 0x00F802E5, 0x00F90845,
893 0x00FA0089, 0x00FB0A09,
894 0x00FC008A, 0x00FD0A0A,
895 0x00FE02A9, 0x00FF0062,
899 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0);
901 /* 1. make mask bitmap's dc */
902 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
903 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
905 /* 2. make masked Background bitmap */
907 /* 2.1 make bitmap */
908 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
909 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
910 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
912 /* 2.2 draw dest bitmap and mask */
913 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
914 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
915 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
, 0, 0);
917 /* 3. make masked Foreground bitmap */
919 /* 3.1 make bitmap */
920 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
921 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
922 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
924 /* 3.2 draw src bitmap and mask */
925 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
926 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
927 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
, 0, 0);
929 /* 4. combine two bitmap and copy it to hdcDest */
930 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
, 0, 0);
931 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
, 0, 0);
933 /* 5. restore all object */
934 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
935 NtGdiSelectObject(hDC1
, hOldBitmap2
);
936 NtGdiSelectObject(hDC2
, hOldBitmap3
);
938 /* 6. delete all temp object */
939 NtGdiDeleteObject(hBitmap2
);
940 NtGdiDeleteObject(hBitmap3
);
944 NtGdiDeleteDC(hDCMask
);
962 IN DWORD crBackColor
)
977 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
978 if (bmp
== NULL
|| Bits
== NULL
)
985 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
989 /* Only get entire lines */
990 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
991 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
993 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
995 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
996 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
1000 bmp
->SurfObj
.sizlBitmap
.cx
,
1001 bmp
->SurfObj
.sizlBitmap
.cy
,
1002 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
1006 /* FIXME: call DDI specific function here if available */
1009 DPRINT ("Calling device specific BitmapBits\n");
1010 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
1012 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
1016 DPRINT ("BitmapBits == NULL??\n");
1023 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
1027 BITMAPOBJ_UnlockBitmap(bmp
);
1033 NtGdiSetBitmapDimensionEx(
1041 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1049 *Size
= bmp
->dimension
;
1051 bmp
->dimension
.cx
= Width
;
1052 bmp
->dimension
.cy
= Height
;
1054 BITMAPOBJ_UnlockBitmap (bmp
);
1066 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1068 return NtGdiGetPixel(hDC
,X
,Y
);
1070 return ((COLORREF
) -1);
1080 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
, NULL
);
1083 if (NewBrush
== NULL
)
1085 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1086 if (OldBrush
== NULL
)
1088 NtGdiDeleteObject(NewBrush
);
1091 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1092 NtGdiSelectObject(hDC
, OldBrush
);
1093 NtGdiDeleteObject(NewBrush
);
1110 IN DWORD dwBackColor
)
1114 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1118 XLATEOBJ
*XlateObj
= NULL
;
1119 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1120 PGDIBRUSHOBJ BrushObj
;
1121 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1122 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1124 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1126 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1129 DCDest
= DC_LockDc(hDCDest
);
1132 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1133 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1138 DC_UnlockDc(DCDest
);
1139 /* Yes, Windows really returns TRUE in this case */
1145 if (hDCSrc
!= hDCDest
)
1147 DCSrc
= DC_LockDc(hDCSrc
);
1150 DC_UnlockDc(DCDest
);
1151 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1152 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1158 DC_UnlockDc(DCDest
);
1159 /* Yes, Windows really returns TRUE in this case */
1173 /* Offset the destination and source by the origin of their DCs. */
1174 XOriginDest
+= DCDest
->w
.DCOrgX
;
1175 YOriginDest
+= DCDest
->w
.DCOrgY
;
1178 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1179 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1182 DestRect
.left
= XOriginDest
;
1183 DestRect
.top
= YOriginDest
;
1184 DestRect
.right
= XOriginDest
+WidthDest
;
1185 DestRect
.bottom
= YOriginDest
+HeightDest
;
1187 SourceRect
.left
= XOriginSrc
;
1188 SourceRect
.top
= YOriginSrc
;
1189 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1190 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1192 /* Determine surfaces to be used in the bitblt */
1193 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1196 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1197 BitmapSrc
= BitmapDest
;
1199 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1208 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1209 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1210 if ( SourceRect
.left
< 0 )
1212 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1213 SourceRect
.left
= 0;
1215 if ( SourceRect
.top
< 0 )
1217 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1220 if ( SourceRect
.right
< -1 )
1222 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1223 SourceRect
.right
= -1;
1225 if ( SourceRect
.bottom
< -1 )
1227 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1228 SourceRect
.bottom
= -1;
1230 if ( SourceRect
.right
> sw
)
1232 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1233 SourceRect
.right
= sw
;
1235 if ( SourceRect
.bottom
> sh
)
1237 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1238 SourceRect
.bottom
= sh
;
1242 if ( SourceRect
.left
> sw
)
1244 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1245 SourceRect
.left
= 0;
1247 if ( SourceRect
.top
> sh
)
1249 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1252 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1254 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1262 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1263 if (NULL
== BrushObj
)
1265 if (UsesSource
&& hDCSrc
!= hDCDest
)
1269 DC_UnlockDc(DCDest
);
1270 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1279 /* Create the XLATEOBJ. */
1282 if (DCDest
->w
.hPalette
!= 0)
1283 DestPalette
= DCDest
->w
.hPalette
;
1285 if (DCSrc
->w
.hPalette
!= 0)
1286 SourcePalette
= DCSrc
->w
.hPalette
;
1288 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1289 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1290 if (NULL
== XlateObj
)
1292 if (UsesSource
&& hDCSrc
!= hDCDest
)
1296 DC_UnlockDc(DCDest
);
1297 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1302 /* Perform the bitblt operation */
1303 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1304 NULL
, DCDest
->CombinedClip
, XlateObj
,
1305 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1309 EngDeleteXlate(XlateObj
);
1312 BRUSHOBJ_UnlockBrush(BrushObj
);
1315 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1317 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1319 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1320 if (UsesSource
&& hDCSrc
!= hDCDest
)
1324 DC_UnlockDc(DCDest
);
1341 BLENDFUNCTION BlendFunc
,
1346 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1347 RECTL DestRect
, SourceRect
;
1350 BLENDOBJ BlendObj
= {BlendFunc
};
1351 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1353 DCDest
= DC_LockDc(hDCDest
);
1356 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
);
1357 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1362 DC_UnlockDc(DCDest
);
1363 /* Yes, Windows really returns TRUE in this case */
1367 if (hDCSrc
!= hDCDest
)
1369 DCSrc
= DC_LockDc(hDCSrc
);
1372 DC_UnlockDc(DCDest
);
1373 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc
);
1374 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1380 DC_UnlockDc(DCDest
);
1381 /* Yes, Windows really returns TRUE in this case */
1390 /* Offset the destination and source by the origin of their DCs. */
1391 XOriginDest
+= DCDest
->w
.DCOrgX
;
1392 YOriginDest
+= DCDest
->w
.DCOrgY
;
1393 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1394 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1396 DestRect
.left
= XOriginDest
;
1397 DestRect
.top
= YOriginDest
;
1398 DestRect
.right
= XOriginDest
+ WidthDest
;
1399 DestRect
.bottom
= YOriginDest
+ HeightDest
;
1401 SourceRect
.left
= XOriginSrc
;
1402 SourceRect
.top
= YOriginSrc
;
1403 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
1404 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
1406 /* Determine surfaces to be used in the bitblt */
1407 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1408 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1409 BitmapSrc
= BitmapDest
;
1411 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1413 /* Create the XLATEOBJ. */
1414 if (DCDest
->w
.hPalette
!= 0)
1415 DestPalette
= DCDest
->w
.hPalette
;
1416 if (DCSrc
->w
.hPalette
!= 0)
1417 SourcePalette
= DCSrc
->w
.hPalette
;
1419 /* KB41464 details how to convert between mono and color */
1420 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
1426 if (DCDest
->w
.bitsPerPixel
== 1)
1428 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
1430 else if (DCSrc
->w
.bitsPerPixel
== 1)
1432 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
1436 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1438 if (NULL
== XlateObj
)
1440 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1441 if (BitmapSrc
!= BitmapDest
)
1442 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1443 DC_UnlockDc(DCDest
);
1444 if (hDCSrc
!= hDCDest
)
1446 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1451 /* Perform the alpha blend operation */
1452 Status
= IntEngAlphaBlend(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1453 DCDest
->CombinedClip
, XlateObj
,
1454 &DestRect
, &SourceRect
, &BlendObj
);
1456 if (XlateObj
!= NULL
)
1457 EngDeleteXlate(XlateObj
);
1459 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1460 if (BitmapSrc
!= BitmapDest
)
1461 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1462 DC_UnlockDc(DCDest
);
1463 if (hDCSrc
!= hDCDest
)
1469 /* Internal Functions */
1472 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1478 return 2 * ((bmWidth
+15) >> 4);
1481 bmWidth
*= 3; /* fall through */
1483 return bmWidth
+ (bmWidth
& 1);
1493 return 2 * ((bmWidth
+3) >> 2);
1502 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1506 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1512 if (hBitmap
== NULL
)
1515 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1519 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1521 if (Bitmap
->SurfObj
.lDelta
>= 0)
1522 bm
.bmHeight
= -bm
.bmHeight
;
1524 res
= IntCreateBitmapIndirect(&bm
);
1529 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1530 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1531 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1535 GDIOBJ_UnlockObjByPtr(Bitmap
);
1541 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1545 if(count
< (INT
) sizeof(DIBSECTION
))
1547 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1551 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1553 memcpy(buffer
, bmp
->dib
, count
);
1559 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1561 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1562 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1563 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1564 Bitmap
.bmPlanes
= 1;
1565 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1566 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1567 memcpy(buffer
, &Bitmap
, count
);