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.
22 #define IN_RECT(r,x,y) \
44 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
46 POINTL SourcePoint
, BrushOrigin
;
48 XLATEOBJ
*XlateObj
= NULL
;
49 HPALETTE SourcePalette
= 0, DestPalette
= 0;
50 PGDIBRUSHOBJ BrushObj
;
51 GDIBRUSHINST BrushInst
;
52 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
53 BOOL UsesPattern
= ROP3_USES_PATTERN(ROP
);
55 DCDest
= DC_LockDc(hDCDest
);
58 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
59 SetLastWin32Error(ERROR_INVALID_HANDLE
);
65 /* Yes, Windows really returns TRUE in this case */
71 if (hDCSrc
!= hDCDest
)
73 DCSrc
= DC_LockDc(hDCSrc
);
77 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
78 SetLastWin32Error(ERROR_INVALID_HANDLE
);
85 /* Yes, Windows really returns TRUE in this case */
99 /* Offset the destination and source by the origin of their DCs. */
100 XDest
+= DCDest
->w
.DCOrgX
;
101 YDest
+= DCDest
->w
.DCOrgY
;
104 XSrc
+= DCSrc
->w
.DCOrgX
;
105 YSrc
+= DCSrc
->w
.DCOrgY
;
108 DestRect
.left
= XDest
;
109 DestRect
.top
= YDest
;
110 DestRect
.right
= XDest
+Width
;
111 DestRect
.bottom
= YDest
+Height
;
113 SourcePoint
.x
= XSrc
;
114 SourcePoint
.y
= YSrc
;
119 /* Determine surfaces to be used in the bitblt */
120 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
123 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
124 BitmapSrc
= BitmapDest
;
126 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
135 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
136 if (NULL
== BrushObj
)
138 if (UsesSource
&& hDCSrc
!= hDCDest
)
142 if(BitmapDest
!= NULL
)
144 BITMAPOBJ_UnlockBitmap(BitmapDest
);
146 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
148 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
151 SetLastWin32Error(ERROR_INVALID_HANDLE
);
154 BrushOrigin
= BrushObj
->ptOrigin
;
155 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
162 /* Create the XLATEOBJ. */
165 if (DCDest
->w
.hPalette
!= 0)
166 DestPalette
= DCDest
->w
.hPalette
;
168 if (DCSrc
->w
.hPalette
!= 0)
169 SourcePalette
= DCSrc
->w
.hPalette
;
171 /* KB41464 details how to convert between mono and color */
172 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
178 if (DCDest
->w
.bitsPerPixel
== 1)
180 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
182 else if (DCSrc
->w
.bitsPerPixel
== 1)
184 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
188 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
190 if (NULL
== XlateObj
)
192 if (UsesSource
&& hDCSrc
!= hDCDest
)
197 if(BitmapDest
!= NULL
)
199 BITMAPOBJ_UnlockBitmap(BitmapDest
);
201 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
203 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
207 BRUSHOBJ_UnlockBrush(BrushObj
);
209 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
215 /* Perform the bitblt operation */
216 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
, NULL
,
217 DCDest
->CombinedClip
, XlateObj
, &DestRect
,
219 BrushObj
? &BrushInst
.BrushObject
: NULL
,
220 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
222 if (UsesSource
&& XlateObj
!= NULL
)
223 EngDeleteXlate(XlateObj
);
225 if(BitmapDest
!= NULL
)
227 BITMAPOBJ_UnlockBitmap(BitmapDest
);
229 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
231 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
233 if (BrushObj
!= NULL
)
235 BRUSHOBJ_UnlockBrush(BrushObj
);
237 if (UsesSource
&& hDCSrc
!= hDCDest
)
262 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
264 HPALETTE SourcePalette
= 0, DestPalette
= 0;
265 PPALGDI PalDestGDI
, PalSourceGDI
;
266 USHORT PalDestMode
, PalSrcMode
;
267 ULONG TransparentColor
= 0;
270 if(!(DCDest
= DC_LockDc(hdcDst
)))
272 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
273 SetLastWin32Error(ERROR_INVALID_HANDLE
);
279 /* Yes, Windows really returns TRUE in this case */
283 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
286 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
287 SetLastWin32Error(ERROR_INVALID_HANDLE
);
301 /* Yes, Windows really returns TRUE in this case */
305 /* Offset positions */
306 xDst
+= DCDest
->w
.DCOrgX
;
307 yDst
+= DCDest
->w
.DCOrgY
;
308 xSrc
+= DCSrc
->w
.DCOrgX
;
309 ySrc
+= DCSrc
->w
.DCOrgY
;
311 if(DCDest
->w
.hPalette
)
312 DestPalette
= DCDest
->w
.hPalette
;
314 if(DCSrc
->w
.hPalette
)
315 SourcePalette
= DCSrc
->w
.hPalette
;
317 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
321 SetLastWin32Error(ERROR_INVALID_HANDLE
);
324 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
326 PALETTE_UnlockPalette(PalSourceGDI
);
329 SetLastWin32Error(ERROR_INVALID_HANDLE
);
332 if(DestPalette
!= SourcePalette
)
334 PalDestMode
= PalDestGDI
->Mode
;
335 PalSrcMode
= PalSourceGDI
->Mode
;
336 PALETTE_UnlockPalette(PalDestGDI
);
340 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
342 PALETTE_UnlockPalette(PalSourceGDI
);
344 /* Translate Transparent (RGB) Color to the source palette */
345 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
347 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
348 EngDeleteXlate(XlateObj
);
351 /* Create the XLATE object to convert colors between source and destination */
352 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
354 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
355 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
357 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
358 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
363 rcDest
.right
= rcDest
.left
+ cxDst
;
364 rcDest
.bottom
= rcDest
.top
+ cyDst
;
367 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
368 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
370 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
372 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
376 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
377 DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
378 TransparentColor
, 0);
381 BITMAPOBJ_UnlockBitmap(BitmapDest
);
382 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
390 EngDeleteXlate(XlateObj
);
407 /* NOTE: Windows also doesn't store nr. of planes separately! */
408 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
410 /* Check parameters */
411 if (!Height
|| !Width
)
413 Size
.cx
= Size
.cy
= 1;
417 Size
.cx
= abs(Width
);
418 Size
.cy
= abs(Height
);
421 /* Create the bitmap object. */
422 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
423 BitmapFormat(BitsPerPel
, BI_RGB
),
424 (Height
< 0 ? BMF_TOPDOWN
: 0) |
425 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
428 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
432 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
433 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
435 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
436 /* FIXME - bmp can be NULL!!!!!! */
437 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
438 BITMAPOBJ_UnlockBitmap( bmp
);
441 * NOTE: It's ugly practice, but we are using the object even
442 * after unlocking. Since the handle is currently known only
443 * to us it should be safe.
448 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
455 BITMAP_Cleanup(PVOID ObjectBody
)
457 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
458 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
459 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
461 if (pBmp
->dib
== NULL
)
463 ExFreePool(pBmp
->SurfObj
.pvBits
);
467 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
469 if (pBmp
->hDIBPalette
)
471 NtGdiDeleteObject(pBmp
->hDIBPalette
);
475 if (NULL
!= pBmp
->BitsLock
)
477 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
478 pBmp
->BitsLock
= NULL
;
486 IntCreateCompatibleBitmap(
495 if ((Width
>= 0x10000) || (Height
>= 0x10000))
497 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
501 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
502 if (0 == Width
|| 0 == Height
)
504 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
508 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
515 NtGdiCreateCompatibleBitmap(
525 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
529 SetLastWin32Error(ERROR_INVALID_HANDLE
);
533 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
535 DPRINT ("\t\t%04x\n", Bmp
);
541 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
543 return NtGdiCreateBitmap (BM
->bmWidth
,
551 NtGdiCreateDiscardableBitmap(
556 /* FIXME: this probably should do something else */
557 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
568 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
570 /* lie and say we succeded */
581 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
585 NtGdiGetBitmapDimensionEx(
591 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
597 *Dimension
= bmp
->dimension
;
599 BITMAPOBJ_UnlockBitmap(bmp
);
605 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
608 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
609 BOOL bInRect
= FALSE
;
610 BITMAPOBJ
*BitmapObject
;
611 SURFOBJ
*SurfaceObject
;
615 dc
= DC_LockDc (hDC
);
619 SetLastWin32Error(ERROR_INVALID_HANDLE
);
627 XPos
+= dc
->w
.DCOrgX
;
628 YPos
+= dc
->w
.DCOrgY
;
629 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
632 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
633 SurfaceObject
= &BitmapObject
->SurfObj
;
636 if ( dc
->w
.hPalette
!= 0 )
637 Pal
= dc
->w
.hPalette
;
638 /* FIXME: Verify if it shouldn't be PAL_BGR! */
639 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
642 // check if this DC has a DIB behind it...
643 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
645 ASSERT ( SurfaceObject
->lDelta
);
646 Result
= XLATEOBJ_iXlate(XlateObj
,
647 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
649 EngDeleteXlate(XlateObj
);
651 BITMAPOBJ_UnlockBitmap(BitmapObject
);
656 // if Result is still CLR_INVALID, then the "quick" method above didn't work
657 if ( bInRect
&& Result
== CLR_INVALID
)
659 // FIXME: create a 1x1 32BPP DIB, and blit to it
660 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
663 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
665 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
666 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
667 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
670 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
675 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
676 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
678 // our bitmap is no longer selected, so we can access it's stuff...
679 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
682 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
683 BITMAPOBJ_UnlockBitmap ( bmpobj
);
686 NtGdiDeleteObject ( hBmpTmp
);
688 NtGdiDeleteDC ( hDCTmp
);
695 /***********************************************************************
697 * Ported from WINE by sedwards 11-4-03
699 * Someone thought it would be faster to do it here and then switch back
700 * to GDI32. I dunno. Write a test and let me know.
704 SwapROP3_SrcDst(BYTE bRop3
)
706 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
709 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
710 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
711 #define DSTCOPY 0x00AA0029
712 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
716 HDC hdcDest
, INT nXDest
, INT nYDest
,
717 INT nWidth
, INT nHeight
, HDC hdcSrc
,
718 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
719 INT xMask
, INT yMask
, DWORD dwRop
)
721 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
722 HDC hDCMask
, hDC1
, hDC2
;
723 static const DWORD ROP3Table
[256] =
725 0x00000042, 0x00010289,
726 0x00020C89, 0x000300AA,
727 0x00040C88, 0x000500A9,
728 0x00060865, 0x000702C5,
729 0x00080F08, 0x00090245,
730 0x000A0329, 0x000B0B2A,
731 0x000C0324, 0x000D0B25,
732 0x000E08A5, 0x000F0001,
733 0x00100C85, 0x001100A6,
734 0x00120868, 0x001302C8,
735 0x00140869, 0x001502C9,
736 0x00165CCA, 0x00171D54,
737 0x00180D59, 0x00191CC8,
738 0x001A06C5, 0x001B0768,
739 0x001C06CA, 0x001D0766,
740 0x001E01A5, 0x001F0385,
741 0x00200F09, 0x00210248,
742 0x00220326, 0x00230B24,
743 0x00240D55, 0x00251CC5,
744 0x002606C8, 0x00271868,
745 0x00280369, 0x002916CA,
746 0x002A0CC9, 0x002B1D58,
747 0x002C0784, 0x002D060A,
748 0x002E064A, 0x002F0E2A,
749 0x0030032A, 0x00310B28,
750 0x00320688, 0x00330008,
751 0x003406C4, 0x00351864,
752 0x003601A8, 0x00370388,
753 0x0038078A, 0x00390604,
754 0x003A0644, 0x003B0E24,
755 0x003C004A, 0x003D18A4,
756 0x003E1B24, 0x003F00EA,
757 0x00400F0A, 0x00410249,
758 0x00420D5D, 0x00431CC4,
759 0x00440328, 0x00450B29,
760 0x004606C6, 0x0047076A,
761 0x00480368, 0x004916C5,
762 0x004A0789, 0x004B0605,
763 0x004C0CC8, 0x004D1954,
764 0x004E0645, 0x004F0E25,
765 0x00500325, 0x00510B26,
766 0x005206C9, 0x00530764,
767 0x005408A9, 0x00550009,
768 0x005601A9, 0x00570389,
769 0x00580785, 0x00590609,
770 0x005A0049, 0x005B18A9,
771 0x005C0649, 0x005D0E29,
772 0x005E1B29, 0x005F00E9,
773 0x00600365, 0x006116C6,
774 0x00620786, 0x00630608,
775 0x00640788, 0x00650606,
776 0x00660046, 0x006718A8,
777 0x006858A6, 0x00690145,
778 0x006A01E9, 0x006B178A,
779 0x006C01E8, 0x006D1785,
780 0x006E1E28, 0x006F0C65,
781 0x00700CC5, 0x00711D5C,
782 0x00720648, 0x00730E28,
783 0x00740646, 0x00750E26,
784 0x00761B28, 0x007700E6,
785 0x007801E5, 0x00791786,
786 0x007A1E29, 0x007B0C68,
787 0x007C1E24, 0x007D0C69,
788 0x007E0955, 0x007F03C9,
789 0x008003E9, 0x00810975,
790 0x00820C49, 0x00831E04,
791 0x00840C48, 0x00851E05,
792 0x008617A6, 0x008701C5,
793 0x008800C6, 0x00891B08,
794 0x008A0E06, 0x008B0666,
795 0x008C0E08, 0x008D0668,
796 0x008E1D7C, 0x008F0CE5,
797 0x00900C45, 0x00911E08,
798 0x009217A9, 0x009301C4,
799 0x009417AA, 0x009501C9,
800 0x00960169, 0x0097588A,
801 0x00981888, 0x00990066,
802 0x009A0709, 0x009B07A8,
803 0x009C0704, 0x009D07A6,
804 0x009E16E6, 0x009F0345,
805 0x00A000C9, 0x00A11B05,
806 0x00A20E09, 0x00A30669,
807 0x00A41885, 0x00A50065,
808 0x00A60706, 0x00A707A5,
809 0x00A803A9, 0x00A90189,
810 0x00AA0029, 0x00AB0889,
811 0x00AC0744, 0x00AD06E9,
812 0x00AE0B06, 0x00AF0229,
813 0x00B00E05, 0x00B10665,
814 0x00B21974, 0x00B30CE8,
815 0x00B4070A, 0x00B507A9,
816 0x00B616E9, 0x00B70348,
817 0x00B8074A, 0x00B906E6,
818 0x00BA0B09, 0x00BB0226,
819 0x00BC1CE4, 0x00BD0D7D,
820 0x00BE0269, 0x00BF08C9,
821 0x00C000CA, 0x00C11B04,
822 0x00C21884, 0x00C3006A,
823 0x00C40E04, 0x00C50664,
824 0x00C60708, 0x00C707AA,
825 0x00C803A8, 0x00C90184,
826 0x00CA0749, 0x00CB06E4,
827 0x00CC0020, 0x00CD0888,
828 0x00CE0B08, 0x00CF0224,
829 0x00D00E0A, 0x00D1066A,
830 0x00D20705, 0x00D307A4,
831 0x00D41D78, 0x00D50CE9,
832 0x00D616EA, 0x00D70349,
833 0x00D80745, 0x00D906E8,
834 0x00DA1CE9, 0x00DB0D75,
835 0x00DC0B04, 0x00DD0228,
836 0x00DE0268, 0x00DF08C8,
837 0x00E003A5, 0x00E10185,
838 0x00E20746, 0x00E306EA,
839 0x00E40748, 0x00E506E5,
840 0x00E61CE8, 0x00E70D79,
841 0x00E81D74, 0x00E95CE6,
842 0x00EA02E9, 0x00EB0849,
843 0x00EC02E8, 0x00ED0848,
844 0x00EE0086, 0x00EF0A08,
845 0x00F00021, 0x00F10885,
846 0x00F20B05, 0x00F3022A,
847 0x00F40B0A, 0x00F50225,
848 0x00F60265, 0x00F708C5,
849 0x00F802E5, 0x00F90845,
850 0x00FA0089, 0x00FB0A09,
851 0x00FC008A, 0x00FD0A0A,
852 0x00FE02A9, 0x00FF0062,
856 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
858 /* 1. make mask bitmap's dc */
859 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
860 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
862 /* 2. make masked Background bitmap */
864 /* 2.1 make bitmap */
865 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
866 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
867 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
869 /* 2.2 draw dest bitmap and mask */
870 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
871 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
872 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
874 /* 3. make masked Foreground bitmap */
876 /* 3.1 make bitmap */
877 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
878 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
879 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
881 /* 3.2 draw src bitmap and mask */
882 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
883 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
884 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
886 /* 4. combine two bitmap and copy it to hdcDest */
887 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
888 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
890 /* 5. restore all object */
891 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
892 NtGdiSelectObject(hDC1
, hOldBitmap2
);
893 NtGdiSelectObject(hDC2
, hOldBitmap3
);
895 /* 6. delete all temp object */
896 NtGdiDeleteObject(hBitmap2
);
897 NtGdiDeleteObject(hBitmap3
);
901 NtGdiDeleteDC(hDCMask
);
932 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
933 if (bmp
== NULL
|| Bits
== NULL
)
940 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
944 /* Only get entire lines */
945 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
946 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
948 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
950 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
951 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
955 bmp
->SurfObj
.sizlBitmap
.cx
,
956 bmp
->SurfObj
.sizlBitmap
.cy
,
957 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
961 /* FIXME: call DDI specific function here if available */
964 DPRINT ("Calling device specific BitmapBits\n");
965 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
967 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
971 DPRINT ("BitmapBits == NULL??\n");
978 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
982 BITMAPOBJ_UnlockBitmap(bmp
);
988 NtGdiSetBitmapDimensionEx(
996 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1004 *Size
= bmp
->dimension
;
1006 bmp
->dimension
.cx
= Width
;
1007 bmp
->dimension
.cy
= Height
;
1009 BITMAPOBJ_UnlockBitmap (bmp
);
1021 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
1022 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1026 return ((COLORREF
) -1);
1036 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1039 if (NewBrush
== NULL
)
1041 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1042 if (OldBrush
== NULL
)
1044 NtGdiDeleteObject(NewBrush
);
1047 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1048 NtGdiSelectObject(hDC
, OldBrush
);
1049 NtGdiDeleteObject(NewBrush
);
1069 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1073 XLATEOBJ
*XlateObj
= NULL
;
1074 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1075 PGDIBRUSHOBJ BrushObj
;
1076 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1077 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1079 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1081 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1084 DCDest
= DC_LockDc(hDCDest
);
1087 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1088 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1093 DC_UnlockDc(DCDest
);
1094 /* Yes, Windows really returns TRUE in this case */
1100 if (hDCSrc
!= hDCDest
)
1102 DCSrc
= DC_LockDc(hDCSrc
);
1105 DC_UnlockDc(DCDest
);
1106 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1107 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1113 DC_UnlockDc(DCDest
);
1114 /* Yes, Windows really returns TRUE in this case */
1128 /* Offset the destination and source by the origin of their DCs. */
1129 XOriginDest
+= DCDest
->w
.DCOrgX
;
1130 YOriginDest
+= DCDest
->w
.DCOrgY
;
1133 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1134 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1137 DestRect
.left
= XOriginDest
;
1138 DestRect
.top
= YOriginDest
;
1139 DestRect
.right
= XOriginDest
+WidthDest
;
1140 DestRect
.bottom
= YOriginDest
+HeightDest
;
1142 SourceRect
.left
= XOriginSrc
;
1143 SourceRect
.top
= YOriginSrc
;
1144 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1145 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1147 /* Determine surfaces to be used in the bitblt */
1148 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1151 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1152 BitmapSrc
= BitmapDest
;
1154 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1163 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1164 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1165 if ( SourceRect
.left
< 0 )
1167 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1168 SourceRect
.left
= 0;
1170 if ( SourceRect
.top
< 0 )
1172 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1175 if ( SourceRect
.right
< -1 )
1177 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1178 SourceRect
.right
= -1;
1180 if ( SourceRect
.bottom
< -1 )
1182 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1183 SourceRect
.bottom
= -1;
1185 if ( SourceRect
.right
> sw
)
1187 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1188 SourceRect
.right
= sw
;
1190 if ( SourceRect
.bottom
> sh
)
1192 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1193 SourceRect
.bottom
= sh
;
1197 if ( SourceRect
.left
> sw
)
1199 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1200 SourceRect
.left
= 0;
1202 if ( SourceRect
.top
> sh
)
1204 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1207 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1209 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1217 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1218 if (NULL
== BrushObj
)
1220 if (UsesSource
&& hDCSrc
!= hDCDest
)
1224 DC_UnlockDc(DCDest
);
1225 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1234 /* Create the XLATEOBJ. */
1237 if (DCDest
->w
.hPalette
!= 0)
1238 DestPalette
= DCDest
->w
.hPalette
;
1240 if (DCSrc
->w
.hPalette
!= 0)
1241 SourcePalette
= DCSrc
->w
.hPalette
;
1243 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1244 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1245 if (NULL
== XlateObj
)
1247 if (UsesSource
&& hDCSrc
!= hDCDest
)
1251 DC_UnlockDc(DCDest
);
1252 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1257 /* Perform the bitblt operation */
1258 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1259 NULL
, DCDest
->CombinedClip
, XlateObj
,
1260 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1264 EngDeleteXlate(XlateObj
);
1267 BRUSHOBJ_UnlockBrush(BrushObj
);
1270 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1272 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1274 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1275 if (UsesSource
&& hDCSrc
!= hDCDest
)
1279 DC_UnlockDc(DCDest
);
1284 /* Internal Functions */
1287 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1293 return 2 * ((bmWidth
+15) >> 4);
1296 bmWidth
*= 3; /* fall through */
1298 return bmWidth
+ (bmWidth
& 1);
1308 return 2 * ((bmWidth
+3) >> 2);
1317 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1321 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1327 if (hBitmap
== NULL
)
1330 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1334 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1336 if (Bitmap
->SurfObj
.lDelta
>= 0)
1337 bm
.bmHeight
= -bm
.bmHeight
;
1339 res
= NtGdiCreateBitmapIndirect(&bm
);
1344 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1345 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1346 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1350 GDIOBJ_UnlockObjByPtr(Bitmap
);
1356 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1360 if(count
< (INT
) sizeof(DIBSECTION
))
1362 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1366 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1368 memcpy(buffer
, bmp
->dib
, count
);
1374 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1376 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1377 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1378 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1379 Bitmap
.bmPlanes
= 1;
1380 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1381 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1382 memcpy(buffer
, &Bitmap
, count
);