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
= 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
);
403 static FASTCALL HBITMAP
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
);
440 /* FIXME - bmp can be NULL!!!!!! */
441 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
442 BITMAPOBJ_UnlockBitmap( bmp
);
445 * NOTE: It's ugly practice, but we are using the object even
446 * after unlocking. Since the handle is currently known only
447 * to us it should be safe.
450 if (NULL
!= BM
->bmBits
)
452 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, BM
->bmBits
);
464 IN OPTIONAL LPBYTE Bits
)
470 BM
.bmHeight
= Height
;
471 BM
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes(Width
, Planes
* BitsPixel
);
472 BM
.bmPlanes
= Planes
;
473 BM
.bmBitsPixel
= BitsPixel
;
476 return IntCreateBitmapIndirect(&BM
);
480 BITMAP_Cleanup(PVOID ObjectBody
)
482 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
483 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
484 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
486 if (pBmp
->dib
== NULL
)
488 ExFreePool(pBmp
->SurfObj
.pvBits
);
492 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
494 if (pBmp
->hDIBPalette
)
496 NtGdiDeleteObject(pBmp
->hDIBPalette
);
500 if (NULL
!= pBmp
->BitsLock
)
502 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
503 pBmp
->BitsLock
= NULL
;
511 IntCreateCompatibleBitmap(
520 if ((Width
>= 0x10000) || (Height
>= 0x10000))
522 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
526 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
527 if (0 == Width
|| 0 == Height
)
529 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
533 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
540 NtGdiCreateCompatibleBitmap(
550 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
554 SetLastWin32Error(ERROR_INVALID_HANDLE
);
558 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
560 DPRINT ("\t\t%04x\n", Bmp
);
566 NtGdiCreateBitmapIndirect(CONST BITMAP
*UnsafeBM
)
569 NTSTATUS Status
= STATUS_SUCCESS
;
573 ProbeForRead(UnsafeBM
, sizeof(BITMAP
), 1);
575 if (NULL
!= BM
.bmBits
)
577 ProbeForRead(BM
.bmBits
, BM
.bmWidthBytes
* abs(BM
.bmHeight
), 2);
582 Status
= _SEH_GetExceptionCode();
585 if(!NT_SUCCESS(Status
))
587 SetLastNtError(Status
);
591 return IntCreateBitmapIndirect(&BM
);
595 NtGdiCreateDiscardableBitmap(
600 /* FIXME: this probably should do something else */
601 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
612 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
614 /* lie and say we succeded */
625 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
629 NtGdiGetBitmapDimensionEx(
635 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
641 *Dimension
= bmp
->dimension
;
643 BITMAPOBJ_UnlockBitmap(bmp
);
649 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
652 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
653 BOOL bInRect
= FALSE
;
654 BITMAPOBJ
*BitmapObject
;
655 SURFOBJ
*SurfaceObject
;
659 dc
= DC_LockDc (hDC
);
663 SetLastWin32Error(ERROR_INVALID_HANDLE
);
671 XPos
+= dc
->w
.DCOrgX
;
672 YPos
+= dc
->w
.DCOrgY
;
673 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
676 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
677 SurfaceObject
= &BitmapObject
->SurfObj
;
680 if ( dc
->w
.hPalette
!= 0 )
681 Pal
= dc
->w
.hPalette
;
682 /* FIXME: Verify if it shouldn't be PAL_BGR! */
683 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
686 // check if this DC has a DIB behind it...
687 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
689 ASSERT ( SurfaceObject
->lDelta
);
690 Result
= XLATEOBJ_iXlate(XlateObj
,
691 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
693 EngDeleteXlate(XlateObj
);
695 BITMAPOBJ_UnlockBitmap(BitmapObject
);
700 // if Result is still CLR_INVALID, then the "quick" method above didn't work
701 if ( bInRect
&& Result
== CLR_INVALID
)
703 // FIXME: create a 1x1 32BPP DIB, and blit to it
704 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
707 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
709 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
710 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
711 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
714 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
719 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
, 0, 0 );
720 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
722 // our bitmap is no longer selected, so we can access it's stuff...
723 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
726 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
727 BITMAPOBJ_UnlockBitmap ( bmpobj
);
730 NtGdiDeleteObject ( hBmpTmp
);
732 NtGdiDeleteDC ( hDCTmp
);
739 /***********************************************************************
741 * Ported from WINE by sedwards 11-4-03
743 * Someone thought it would be faster to do it here and then switch back
744 * to GDI32. I dunno. Write a test and let me know.
748 SwapROP3_SrcDst(BYTE bRop3
)
750 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
753 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
754 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
755 #define DSTCOPY 0x00AA0029
756 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
760 HDC hdcDest
, INT nXDest
, INT nYDest
,
761 INT nWidth
, INT nHeight
, HDC hdcSrc
,
762 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
763 INT xMask
, INT yMask
, DWORD dwRop
,
764 IN DWORD crBackColor
)
766 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
767 HDC hDCMask
, hDC1
, hDC2
;
768 static const DWORD ROP3Table
[256] =
770 0x00000042, 0x00010289,
771 0x00020C89, 0x000300AA,
772 0x00040C88, 0x000500A9,
773 0x00060865, 0x000702C5,
774 0x00080F08, 0x00090245,
775 0x000A0329, 0x000B0B2A,
776 0x000C0324, 0x000D0B25,
777 0x000E08A5, 0x000F0001,
778 0x00100C85, 0x001100A6,
779 0x00120868, 0x001302C8,
780 0x00140869, 0x001502C9,
781 0x00165CCA, 0x00171D54,
782 0x00180D59, 0x00191CC8,
783 0x001A06C5, 0x001B0768,
784 0x001C06CA, 0x001D0766,
785 0x001E01A5, 0x001F0385,
786 0x00200F09, 0x00210248,
787 0x00220326, 0x00230B24,
788 0x00240D55, 0x00251CC5,
789 0x002606C8, 0x00271868,
790 0x00280369, 0x002916CA,
791 0x002A0CC9, 0x002B1D58,
792 0x002C0784, 0x002D060A,
793 0x002E064A, 0x002F0E2A,
794 0x0030032A, 0x00310B28,
795 0x00320688, 0x00330008,
796 0x003406C4, 0x00351864,
797 0x003601A8, 0x00370388,
798 0x0038078A, 0x00390604,
799 0x003A0644, 0x003B0E24,
800 0x003C004A, 0x003D18A4,
801 0x003E1B24, 0x003F00EA,
802 0x00400F0A, 0x00410249,
803 0x00420D5D, 0x00431CC4,
804 0x00440328, 0x00450B29,
805 0x004606C6, 0x0047076A,
806 0x00480368, 0x004916C5,
807 0x004A0789, 0x004B0605,
808 0x004C0CC8, 0x004D1954,
809 0x004E0645, 0x004F0E25,
810 0x00500325, 0x00510B26,
811 0x005206C9, 0x00530764,
812 0x005408A9, 0x00550009,
813 0x005601A9, 0x00570389,
814 0x00580785, 0x00590609,
815 0x005A0049, 0x005B18A9,
816 0x005C0649, 0x005D0E29,
817 0x005E1B29, 0x005F00E9,
818 0x00600365, 0x006116C6,
819 0x00620786, 0x00630608,
820 0x00640788, 0x00650606,
821 0x00660046, 0x006718A8,
822 0x006858A6, 0x00690145,
823 0x006A01E9, 0x006B178A,
824 0x006C01E8, 0x006D1785,
825 0x006E1E28, 0x006F0C65,
826 0x00700CC5, 0x00711D5C,
827 0x00720648, 0x00730E28,
828 0x00740646, 0x00750E26,
829 0x00761B28, 0x007700E6,
830 0x007801E5, 0x00791786,
831 0x007A1E29, 0x007B0C68,
832 0x007C1E24, 0x007D0C69,
833 0x007E0955, 0x007F03C9,
834 0x008003E9, 0x00810975,
835 0x00820C49, 0x00831E04,
836 0x00840C48, 0x00851E05,
837 0x008617A6, 0x008701C5,
838 0x008800C6, 0x00891B08,
839 0x008A0E06, 0x008B0666,
840 0x008C0E08, 0x008D0668,
841 0x008E1D7C, 0x008F0CE5,
842 0x00900C45, 0x00911E08,
843 0x009217A9, 0x009301C4,
844 0x009417AA, 0x009501C9,
845 0x00960169, 0x0097588A,
846 0x00981888, 0x00990066,
847 0x009A0709, 0x009B07A8,
848 0x009C0704, 0x009D07A6,
849 0x009E16E6, 0x009F0345,
850 0x00A000C9, 0x00A11B05,
851 0x00A20E09, 0x00A30669,
852 0x00A41885, 0x00A50065,
853 0x00A60706, 0x00A707A5,
854 0x00A803A9, 0x00A90189,
855 0x00AA0029, 0x00AB0889,
856 0x00AC0744, 0x00AD06E9,
857 0x00AE0B06, 0x00AF0229,
858 0x00B00E05, 0x00B10665,
859 0x00B21974, 0x00B30CE8,
860 0x00B4070A, 0x00B507A9,
861 0x00B616E9, 0x00B70348,
862 0x00B8074A, 0x00B906E6,
863 0x00BA0B09, 0x00BB0226,
864 0x00BC1CE4, 0x00BD0D7D,
865 0x00BE0269, 0x00BF08C9,
866 0x00C000CA, 0x00C11B04,
867 0x00C21884, 0x00C3006A,
868 0x00C40E04, 0x00C50664,
869 0x00C60708, 0x00C707AA,
870 0x00C803A8, 0x00C90184,
871 0x00CA0749, 0x00CB06E4,
872 0x00CC0020, 0x00CD0888,
873 0x00CE0B08, 0x00CF0224,
874 0x00D00E0A, 0x00D1066A,
875 0x00D20705, 0x00D307A4,
876 0x00D41D78, 0x00D50CE9,
877 0x00D616EA, 0x00D70349,
878 0x00D80745, 0x00D906E8,
879 0x00DA1CE9, 0x00DB0D75,
880 0x00DC0B04, 0x00DD0228,
881 0x00DE0268, 0x00DF08C8,
882 0x00E003A5, 0x00E10185,
883 0x00E20746, 0x00E306EA,
884 0x00E40748, 0x00E506E5,
885 0x00E61CE8, 0x00E70D79,
886 0x00E81D74, 0x00E95CE6,
887 0x00EA02E9, 0x00EB0849,
888 0x00EC02E8, 0x00ED0848,
889 0x00EE0086, 0x00EF0A08,
890 0x00F00021, 0x00F10885,
891 0x00F20B05, 0x00F3022A,
892 0x00F40B0A, 0x00F50225,
893 0x00F60265, 0x00F708C5,
894 0x00F802E5, 0x00F90845,
895 0x00FA0089, 0x00FB0A09,
896 0x00FC008A, 0x00FD0A0A,
897 0x00FE02A9, 0x00FF0062,
901 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0);
903 /* 1. make mask bitmap's dc */
904 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
905 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
907 /* 2. make masked Background bitmap */
909 /* 2.1 make bitmap */
910 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
911 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
912 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
914 /* 2.2 draw dest bitmap and mask */
915 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
, 0, 0);
916 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
), 0, 0);
917 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
, 0, 0);
919 /* 3. make masked Foreground bitmap */
921 /* 3.1 make bitmap */
922 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
923 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
924 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
926 /* 3.2 draw src bitmap and mask */
927 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0);
928 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0,0);
929 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
, 0, 0);
931 /* 4. combine two bitmap and copy it to hdcDest */
932 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
, 0, 0);
933 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
, 0, 0);
935 /* 5. restore all object */
936 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
937 NtGdiSelectObject(hDC1
, hOldBitmap2
);
938 NtGdiSelectObject(hDC2
, hOldBitmap3
);
940 /* 6. delete all temp object */
941 NtGdiDeleteObject(hBitmap2
);
942 NtGdiDeleteObject(hBitmap3
);
946 NtGdiDeleteDC(hDCMask
);
964 IN DWORD crBackColor
)
979 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
980 if (bmp
== NULL
|| Bits
== NULL
)
987 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
991 /* Only get entire lines */
992 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
993 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
995 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
997 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
998 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
1002 bmp
->SurfObj
.sizlBitmap
.cx
,
1003 bmp
->SurfObj
.sizlBitmap
.cy
,
1004 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
1008 /* FIXME: call DDI specific function here if available */
1011 DPRINT ("Calling device specific BitmapBits\n");
1012 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
1014 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
1018 DPRINT ("BitmapBits == NULL??\n");
1025 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
1029 BITMAPOBJ_UnlockBitmap(bmp
);
1035 NtGdiSetBitmapDimensionEx(
1043 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1051 *Size
= bmp
->dimension
;
1053 bmp
->dimension
.cx
= Width
;
1054 bmp
->dimension
.cy
= Height
;
1056 BITMAPOBJ_UnlockBitmap (bmp
);
1068 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1070 return NtGdiGetPixel(hDC
,X
,Y
);
1072 return ((COLORREF
) -1);
1082 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
, NULL
);
1085 if (NewBrush
== NULL
)
1087 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1088 if (OldBrush
== NULL
)
1090 NtGdiDeleteObject(NewBrush
);
1093 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1094 NtGdiSelectObject(hDC
, OldBrush
);
1095 NtGdiDeleteObject(NewBrush
);
1112 IN DWORD dwBackColor
)
1116 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1120 XLATEOBJ
*XlateObj
= NULL
;
1121 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1122 PGDIBRUSHOBJ BrushObj
;
1123 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1124 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1126 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1128 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1131 DCDest
= DC_LockDc(hDCDest
);
1134 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1135 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1140 DC_UnlockDc(DCDest
);
1141 /* Yes, Windows really returns TRUE in this case */
1147 if (hDCSrc
!= hDCDest
)
1149 DCSrc
= DC_LockDc(hDCSrc
);
1152 DC_UnlockDc(DCDest
);
1153 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1154 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1160 DC_UnlockDc(DCDest
);
1161 /* Yes, Windows really returns TRUE in this case */
1175 /* Offset the destination and source by the origin of their DCs. */
1176 XOriginDest
+= DCDest
->w
.DCOrgX
;
1177 YOriginDest
+= DCDest
->w
.DCOrgY
;
1180 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1181 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1184 DestRect
.left
= XOriginDest
;
1185 DestRect
.top
= YOriginDest
;
1186 DestRect
.right
= XOriginDest
+WidthDest
;
1187 DestRect
.bottom
= YOriginDest
+HeightDest
;
1189 SourceRect
.left
= XOriginSrc
;
1190 SourceRect
.top
= YOriginSrc
;
1191 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1192 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1194 /* Determine surfaces to be used in the bitblt */
1195 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1198 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1199 BitmapSrc
= BitmapDest
;
1201 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1210 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1211 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1212 if ( SourceRect
.left
< 0 )
1214 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1215 SourceRect
.left
= 0;
1217 if ( SourceRect
.top
< 0 )
1219 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1222 if ( SourceRect
.right
< -1 )
1224 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1225 SourceRect
.right
= -1;
1227 if ( SourceRect
.bottom
< -1 )
1229 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1230 SourceRect
.bottom
= -1;
1232 if ( SourceRect
.right
> sw
)
1234 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1235 SourceRect
.right
= sw
;
1237 if ( SourceRect
.bottom
> sh
)
1239 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1240 SourceRect
.bottom
= sh
;
1244 if ( SourceRect
.left
> sw
)
1246 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1247 SourceRect
.left
= 0;
1249 if ( SourceRect
.top
> sh
)
1251 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1254 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1256 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1264 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1265 if (NULL
== BrushObj
)
1267 if (UsesSource
&& hDCSrc
!= hDCDest
)
1271 DC_UnlockDc(DCDest
);
1272 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1281 /* Create the XLATEOBJ. */
1284 if (DCDest
->w
.hPalette
!= 0)
1285 DestPalette
= DCDest
->w
.hPalette
;
1287 if (DCSrc
->w
.hPalette
!= 0)
1288 SourcePalette
= DCSrc
->w
.hPalette
;
1290 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1291 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1292 if (NULL
== XlateObj
)
1294 if (UsesSource
&& hDCSrc
!= hDCDest
)
1298 DC_UnlockDc(DCDest
);
1299 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1304 /* Perform the bitblt operation */
1305 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1306 NULL
, DCDest
->CombinedClip
, XlateObj
,
1307 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1311 EngDeleteXlate(XlateObj
);
1314 BRUSHOBJ_UnlockBrush(BrushObj
);
1317 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1319 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1321 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1322 if (UsesSource
&& hDCSrc
!= hDCDest
)
1326 DC_UnlockDc(DCDest
);
1343 BLENDFUNCTION BlendFunc
,
1348 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1349 RECTL DestRect
, SourceRect
;
1352 BLENDOBJ BlendObj
= {BlendFunc
};
1353 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1355 DCDest
= DC_LockDc(hDCDest
);
1358 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
);
1359 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1364 DC_UnlockDc(DCDest
);
1365 /* Yes, Windows really returns TRUE in this case */
1369 if (hDCSrc
!= hDCDest
)
1371 DCSrc
= DC_LockDc(hDCSrc
);
1374 DC_UnlockDc(DCDest
);
1375 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc
);
1376 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1382 DC_UnlockDc(DCDest
);
1383 /* Yes, Windows really returns TRUE in this case */
1392 /* Offset the destination and source by the origin of their DCs. */
1393 XOriginDest
+= DCDest
->w
.DCOrgX
;
1394 YOriginDest
+= DCDest
->w
.DCOrgY
;
1395 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1396 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1398 DestRect
.left
= XOriginDest
;
1399 DestRect
.top
= YOriginDest
;
1400 DestRect
.right
= XOriginDest
+ WidthDest
;
1401 DestRect
.bottom
= YOriginDest
+ HeightDest
;
1403 SourceRect
.left
= XOriginSrc
;
1404 SourceRect
.top
= YOriginSrc
;
1405 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
1406 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
1408 /* Determine surfaces to be used in the bitblt */
1409 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1410 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1411 BitmapSrc
= BitmapDest
;
1413 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1415 /* Create the XLATEOBJ. */
1416 if (DCDest
->w
.hPalette
!= 0)
1417 DestPalette
= DCDest
->w
.hPalette
;
1418 if (DCSrc
->w
.hPalette
!= 0)
1419 SourcePalette
= DCSrc
->w
.hPalette
;
1421 /* KB41464 details how to convert between mono and color */
1422 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
1428 if (DCDest
->w
.bitsPerPixel
== 1)
1430 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
1432 else if (DCSrc
->w
.bitsPerPixel
== 1)
1434 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
1438 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1440 if (NULL
== XlateObj
)
1442 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1443 if (BitmapSrc
!= BitmapDest
)
1444 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1445 DC_UnlockDc(DCDest
);
1446 if (hDCSrc
!= hDCDest
)
1448 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1453 /* Perform the alpha blend operation */
1454 Status
= IntEngAlphaBlend(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1455 DCDest
->CombinedClip
, XlateObj
,
1456 &DestRect
, &SourceRect
, &BlendObj
);
1458 if (XlateObj
!= NULL
)
1459 EngDeleteXlate(XlateObj
);
1461 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1462 if (BitmapSrc
!= BitmapDest
)
1463 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1464 DC_UnlockDc(DCDest
);
1465 if (hDCSrc
!= hDCDest
)
1471 /* Internal Functions */
1474 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1480 return 2 * ((bmWidth
+15) >> 4);
1483 bmWidth
*= 3; /* fall through */
1485 return bmWidth
+ (bmWidth
& 1);
1495 return 2 * ((bmWidth
+3) >> 2);
1504 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1508 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1514 if (hBitmap
== NULL
)
1517 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1521 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1523 if (Bitmap
->SurfObj
.lDelta
>= 0)
1524 bm
.bmHeight
= -bm
.bmHeight
;
1526 res
= IntCreateBitmapIndirect(&bm
);
1531 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1532 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1533 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1537 GDIOBJ_UnlockObjByPtr(Bitmap
);
1543 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1547 if(count
< (INT
) sizeof(DIBSECTION
))
1549 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1553 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1555 memcpy(buffer
, bmp
->dib
, count
);
1561 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1563 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1564 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1565 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1566 Bitmap
.bmPlanes
= 1;
1567 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1568 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1569 memcpy(buffer
, &Bitmap
, count
);