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.
19 /* $Id: bitmaps.c,v 1.77 2004/07/03 17:40:27 navaraf Exp $ */
22 #define IN_RECT(r,x,y) \
44 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
46 POINTL SourcePoint
, BrushOrigin
;
48 PPALGDI PalDestGDI
, PalSourceGDI
;
49 XLATEOBJ
*XlateObj
= NULL
;
50 HPALETTE SourcePalette
= 0, DestPalette
= 0;
51 ULONG SourceMode
, DestMode
;
52 PGDIBRUSHOBJ BrushObj
;
53 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
54 BOOL UsesPattern
= TRUE
;//((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
57 DCDest
= DC_LockDc(hDCDest
);
60 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
61 SetLastWin32Error(ERROR_INVALID_HANDLE
);
67 if (hDCSrc
!= hDCDest
)
69 DCSrc
= DC_LockDc(hDCSrc
);
73 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
74 SetLastWin32Error(ERROR_INVALID_HANDLE
);
88 /* Offset the destination and source by the origin of their DCs. */
89 XDest
+= DCDest
->w
.DCOrgX
;
90 YDest
+= DCDest
->w
.DCOrgY
;
93 XSrc
+= DCSrc
->w
.DCOrgX
;
94 YSrc
+= DCSrc
->w
.DCOrgY
;
97 DestRect
.left
= XDest
;
99 DestRect
.right
= XDest
+Width
;
100 DestRect
.bottom
= YDest
+Height
;
102 SourcePoint
.x
= XSrc
;
103 SourcePoint
.y
= YSrc
;
108 /* Determine surfaces to be used in the bitblt */
109 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
112 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
113 BitmapSrc
= BitmapDest
;
115 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
124 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
125 if (NULL
== BrushObj
)
127 if (UsesSource
&& hDCSrc
!= hDCDest
)
131 DC_UnlockDc(hDCDest
);
132 SetLastWin32Error(ERROR_INVALID_HANDLE
);
135 BrushOrigin
= BrushObj
->ptOrigin
;
142 if (DCDest
->w
.hPalette
!= 0)
143 DestPalette
= DCDest
->w
.hPalette
;
145 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
146 SourcePalette
= DCSrc
->w
.hPalette
;
148 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
149 if (NULL
== PalSourceGDI
)
151 if (UsesSource
&& hDCSrc
!= hDCDest
)
155 DC_UnlockDc(hDCDest
);
156 SetLastWin32Error(ERROR_INVALID_HANDLE
);
159 SourceMode
= PalSourceGDI
->Mode
;
160 PALETTE_UnlockPalette(SourcePalette
);
162 if (DestPalette
== SourcePalette
)
164 DestMode
= SourceMode
;
168 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
169 if (NULL
== PalDestGDI
)
171 if (UsesSource
&& hDCSrc
!= hDCDest
)
175 DC_UnlockDc(hDCDest
);
176 SetLastWin32Error(ERROR_INVALID_HANDLE
);
179 DestMode
= PalDestGDI
->Mode
;
180 PALETTE_UnlockPalette(DestPalette
);
183 /* KB41464 details how to convert between mono and color */
184 if (DCDest
->w
.bitsPerPixel
== 1)
186 XlateObj
= (XLATEOBJ
*)IntEngCreateMonoXlate(SourceMode
, DestPalette
,
187 SourcePalette
, DCSrc
->w
.backgroundColor
);
189 else if (UsesSource
&& 1 == DCSrc
->w
.bitsPerPixel
)
193 Colors
[0] = DCSrc
->w
.textColor
;
194 Colors
[1] = DCSrc
->w
.backgroundColor
;
195 Mono
= PALETTE_AllocPaletteIndexedRGB(2, (RGBQUAD
*)Colors
);
198 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(DestMode
, PAL_INDEXED
, DestPalette
, Mono
);
207 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
209 if (NULL
== XlateObj
)
213 EngDeletePalette(Mono
);
215 if (UsesSource
&& hDCSrc
!= hDCDest
)
219 DC_UnlockDc(hDCDest
);
220 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
224 /* Perform the bitblt operation */
225 Status
= IntEngBitBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
226 &DestRect
, &SourcePoint
, NULL
, &BrushObj
->BrushObject
, &BrushOrigin
, ROP
);
228 EngDeleteXlate(XlateObj
);
229 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
230 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
232 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
236 EngDeletePalette(Mono
);
240 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
242 if (UsesSource
&& hDCSrc
!= hDCDest
)
246 DC_UnlockDc(hDCDest
);
267 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
269 HPALETTE SourcePalette
= 0, DestPalette
= 0;
270 PPALGDI PalDestGDI
, PalSourceGDI
;
271 USHORT PalDestMode
, PalSrcMode
;
272 ULONG TransparentColor
= 0;
275 if(!(DCDest
= DC_LockDc(hdcDst
)))
277 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
278 SetLastWin32Error(ERROR_INVALID_HANDLE
);
282 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
285 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
286 SetLastWin32Error(ERROR_INVALID_HANDLE
);
294 /* Offset positions */
295 xDst
+= DCDest
->w
.DCOrgX
;
296 yDst
+= DCDest
->w
.DCOrgY
;
297 xSrc
+= DCSrc
->w
.DCOrgX
;
298 ySrc
+= DCSrc
->w
.DCOrgY
;
300 if(DCDest
->w
.hPalette
)
301 DestPalette
= DCDest
->w
.hPalette
;
303 if(DCSrc
->w
.hPalette
)
304 SourcePalette
= DCSrc
->w
.hPalette
;
306 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
310 SetLastWin32Error(ERROR_INVALID_HANDLE
);
313 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
315 PALETTE_UnlockPalette(SourcePalette
);
318 SetLastWin32Error(ERROR_INVALID_HANDLE
);
321 if(DestPalette
!= SourcePalette
)
323 PalDestMode
= PalDestGDI
->Mode
;
324 PalSrcMode
= PalSourceGDI
->Mode
;
325 PALETTE_UnlockPalette(DestPalette
);
329 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
331 PALETTE_UnlockPalette(SourcePalette
);
333 /* Translate Transparent (RGB) Color to the source palette */
334 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
336 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
337 EngDeleteXlate(XlateObj
);
340 /* Create the XLATE object to convert colors between source and destination */
341 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
343 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
345 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
350 rcDest
.right
= rcDest
.left
+ cxDst
;
351 rcDest
.bottom
= rcDest
.top
+ cyDst
;
354 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
355 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
357 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
359 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
363 Ret
= IntEngTransparentBlt(BitmapDest
, BitmapSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
364 TransparentColor
, 0);
367 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
368 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
376 EngDeleteXlate(XlateObj
);
393 /* NOTE: Windows also doesn't store nr. of planes separately! */
394 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
396 /* Check parameters */
397 if (!Height
|| !Width
)
399 Size
.cx
= Size
.cy
= 1;
404 Size
.cy
= abs(Height
);
407 /* Create the bitmap object. */
408 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
409 BitmapFormat(BitsPerPel
, BI_RGB
),
410 (Height
> 0 ? 0 : BMF_TOPDOWN
) |
411 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
414 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
418 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
419 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
421 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
422 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
423 BITMAPOBJ_UnlockBitmap( hBitmap
);
426 * NOTE: It's ugly practice, but we are using the object even
427 * after unlocking. Since the handle is currently known only
428 * to us it should be safe.
433 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
440 Bitmap_InternalDelete( PBITMAPOBJ pBmp
)
444 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
445 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
447 if (pBmp
->dib
== NULL
)
449 ExFreePool(pBmp
->SurfObj
.pvBits
);
453 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
462 IntCreateCompatibleBitmap(
471 if ((Width
>= 0x10000) || (Height
>= 0x10000))
473 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
477 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
478 if (0 == Width
|| 0 == Height
)
480 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
484 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
491 NtGdiCreateCompatibleBitmap(
501 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
505 SetLastWin32Error(ERROR_INVALID_HANDLE
);
509 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
511 DPRINT ("\t\t%04x\n", Bmp
);
517 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
519 return NtGdiCreateBitmap (BM
->bmWidth
,
527 NtGdiCreateDiscardableBitmap(
532 /* FIXME: this probably should do something else */
533 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
554 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
558 NtGdiGetBitmapDimensionEx(
564 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
570 *Dimension
= bmp
->dimension
;
572 BITMAPOBJ_UnlockBitmap(hBitmap
);
578 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
581 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
582 BOOL bInRect
= FALSE
;
583 BITMAPOBJ
*BitmapObject
;
584 SURFOBJ
*SurfaceObject
;
590 dc
= DC_LockDc (hDC
);
594 SetLastWin32Error(ERROR_INVALID_HANDLE
);
597 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
600 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
601 SurfaceObject
= &BitmapObject
->SurfObj
;
604 if ( dc
->w
.hPalette
!= 0 )
605 Pal
= dc
->w
.hPalette
;
606 PalGDI
= PALETTE_LockPalette(Pal
);
609 PalMode
= PalGDI
->Mode
;
610 PALETTE_UnlockPalette(Pal
);
612 /* FIXME: Verify if it shouldn't be PAL_BGR! */
613 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, PalMode
, NULL
, Pal
);
616 // check if this DC has a DIB behind it...
617 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
619 ASSERT ( SurfaceObject
->lDelta
);
620 Result
= XLATEOBJ_iXlate(XlateObj
,
621 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
623 EngDeleteXlate(XlateObj
);
627 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
631 // if Result is still CLR_INVALID, then the "quick" method above didn't work
632 if ( bInRect
&& Result
== CLR_INVALID
)
634 // FIXME: create a 1x1 32BPP DIB, and blit to it
635 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
638 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
640 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
641 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
642 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
645 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
650 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
651 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
653 // our bitmap is no longer selected, so we can access it's stuff...
654 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
657 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
658 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
661 NtGdiDeleteObject ( hBmpTmp
);
663 NtGdiDeleteDC ( hDCTmp
);
670 /***********************************************************************
672 * Ported from WINE by sedwards 11-4-03
674 * Someone thought it would be faster to do it here and then switch back
675 * to GDI32. I dunno. Write a test and let me know.
679 SwapROP3_SrcDst(BYTE bRop3
)
681 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
684 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
685 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
686 #define DSTCOPY 0x00AA0029
687 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
691 HDC hdcDest
, INT nXDest
, INT nYDest
,
692 INT nWidth
, INT nHeight
, HDC hdcSrc
,
693 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
694 INT xMask
, INT yMask
, DWORD dwRop
)
696 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
697 HDC hDCMask
, hDC1
, hDC2
;
698 static const DWORD ROP3Table
[256] =
700 0x00000042, 0x00010289,
701 0x00020C89, 0x000300AA,
702 0x00040C88, 0x000500A9,
703 0x00060865, 0x000702C5,
704 0x00080F08, 0x00090245,
705 0x000A0329, 0x000B0B2A,
706 0x000C0324, 0x000D0B25,
707 0x000E08A5, 0x000F0001,
708 0x00100C85, 0x001100A6,
709 0x00120868, 0x001302C8,
710 0x00140869, 0x001502C9,
711 0x00165CCA, 0x00171D54,
712 0x00180D59, 0x00191CC8,
713 0x001A06C5, 0x001B0768,
714 0x001C06CA, 0x001D0766,
715 0x001E01A5, 0x001F0385,
716 0x00200F09, 0x00210248,
717 0x00220326, 0x00230B24,
718 0x00240D55, 0x00251CC5,
719 0x002606C8, 0x00271868,
720 0x00280369, 0x002916CA,
721 0x002A0CC9, 0x002B1D58,
722 0x002C0784, 0x002D060A,
723 0x002E064A, 0x002F0E2A,
724 0x0030032A, 0x00310B28,
725 0x00320688, 0x00330008,
726 0x003406C4, 0x00351864,
727 0x003601A8, 0x00370388,
728 0x0038078A, 0x00390604,
729 0x003A0644, 0x003B0E24,
730 0x003C004A, 0x003D18A4,
731 0x003E1B24, 0x003F00EA,
732 0x00400F0A, 0x00410249,
733 0x00420D5D, 0x00431CC4,
734 0x00440328, 0x00450B29,
735 0x004606C6, 0x0047076A,
736 0x00480368, 0x004916C5,
737 0x004A0789, 0x004B0605,
738 0x004C0CC8, 0x004D1954,
739 0x004E0645, 0x004F0E25,
740 0x00500325, 0x00510B26,
741 0x005206C9, 0x00530764,
742 0x005408A9, 0x00550009,
743 0x005601A9, 0x00570389,
744 0x00580785, 0x00590609,
745 0x005A0049, 0x005B18A9,
746 0x005C0649, 0x005D0E29,
747 0x005E1B29, 0x005F00E9,
748 0x00600365, 0x006116C6,
749 0x00620786, 0x00630608,
750 0x00640788, 0x00650606,
751 0x00660046, 0x006718A8,
752 0x006858A6, 0x00690145,
753 0x006A01E9, 0x006B178A,
754 0x006C01E8, 0x006D1785,
755 0x006E1E28, 0x006F0C65,
756 0x00700CC5, 0x00711D5C,
757 0x00720648, 0x00730E28,
758 0x00740646, 0x00750E26,
759 0x00761B28, 0x007700E6,
760 0x007801E5, 0x00791786,
761 0x007A1E29, 0x007B0C68,
762 0x007C1E24, 0x007D0C69,
763 0x007E0955, 0x007F03C9,
764 0x008003E9, 0x00810975,
765 0x00820C49, 0x00831E04,
766 0x00840C48, 0x00851E05,
767 0x008617A6, 0x008701C5,
768 0x008800C6, 0x00891B08,
769 0x008A0E06, 0x008B0666,
770 0x008C0E08, 0x008D0668,
771 0x008E1D7C, 0x008F0CE5,
772 0x00900C45, 0x00911E08,
773 0x009217A9, 0x009301C4,
774 0x009417AA, 0x009501C9,
775 0x00960169, 0x0097588A,
776 0x00981888, 0x00990066,
777 0x009A0709, 0x009B07A8,
778 0x009C0704, 0x009D07A6,
779 0x009E16E6, 0x009F0345,
780 0x00A000C9, 0x00A11B05,
781 0x00A20E09, 0x00A30669,
782 0x00A41885, 0x00A50065,
783 0x00A60706, 0x00A707A5,
784 0x00A803A9, 0x00A90189,
785 0x00AA0029, 0x00AB0889,
786 0x00AC0744, 0x00AD06E9,
787 0x00AE0B06, 0x00AF0229,
788 0x00B00E05, 0x00B10665,
789 0x00B21974, 0x00B30CE8,
790 0x00B4070A, 0x00B507A9,
791 0x00B616E9, 0x00B70348,
792 0x00B8074A, 0x00B906E6,
793 0x00BA0B09, 0x00BB0226,
794 0x00BC1CE4, 0x00BD0D7D,
795 0x00BE0269, 0x00BF08C9,
796 0x00C000CA, 0x00C11B04,
797 0x00C21884, 0x00C3006A,
798 0x00C40E04, 0x00C50664,
799 0x00C60708, 0x00C707AA,
800 0x00C803A8, 0x00C90184,
801 0x00CA0749, 0x00CB06E4,
802 0x00CC0020, 0x00CD0888,
803 0x00CE0B08, 0x00CF0224,
804 0x00D00E0A, 0x00D1066A,
805 0x00D20705, 0x00D307A4,
806 0x00D41D78, 0x00D50CE9,
807 0x00D616EA, 0x00D70349,
808 0x00D80745, 0x00D906E8,
809 0x00DA1CE9, 0x00DB0D75,
810 0x00DC0B04, 0x00DD0228,
811 0x00DE0268, 0x00DF08C8,
812 0x00E003A5, 0x00E10185,
813 0x00E20746, 0x00E306EA,
814 0x00E40748, 0x00E506E5,
815 0x00E61CE8, 0x00E70D79,
816 0x00E81D74, 0x00E95CE6,
817 0x00EA02E9, 0x00EB0849,
818 0x00EC02E8, 0x00ED0848,
819 0x00EE0086, 0x00EF0A08,
820 0x00F00021, 0x00F10885,
821 0x00F20B05, 0x00F3022A,
822 0x00F40B0A, 0x00F50225,
823 0x00F60265, 0x00F708C5,
824 0x00F802E5, 0x00F90845,
825 0x00FA0089, 0x00FB0A09,
826 0x00FC008A, 0x00FD0A0A,
827 0x00FE02A9, 0x00FF0062,
831 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
833 /* 1. make mask bitmap's dc */
834 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
835 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
837 /* 2. make masked Background bitmap */
839 /* 2.1 make bitmap */
840 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
841 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
842 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
844 /* 2.2 draw dest bitmap and mask */
845 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
846 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
847 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
849 /* 3. make masked Foreground bitmap */
851 /* 3.1 make bitmap */
852 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
853 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
854 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
856 /* 3.2 draw src bitmap and mask */
857 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
858 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
859 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
861 /* 4. combine two bitmap and copy it to hdcDest */
862 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
863 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
865 /* 5. restore all object */
866 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
867 NtGdiSelectObject(hDC1
, hOldBitmap2
);
868 NtGdiSelectObject(hDC2
, hOldBitmap3
);
870 /* 6. delete all temp object */
871 NtGdiDeleteObject(hBitmap2
);
872 NtGdiDeleteObject(hBitmap3
);
876 NtGdiDeleteDC(hDCMask
);
906 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
907 if (bmp
== NULL
|| Bits
== NULL
)
914 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
918 /* Only get entire lines */
919 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
920 if (height
> bmp
->SurfObj
.sizlBitmap
.cx
)
922 height
= bmp
->SurfObj
.sizlBitmap
.cx
;
924 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
925 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
929 bmp
->SurfObj
.sizlBitmap
.cx
,
930 bmp
->SurfObj
.sizlBitmap
.cy
,
931 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
935 /* FIXME: call DDI specific function here if available */
938 DPRINT ("Calling device specific BitmapBits\n");
939 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
941 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
945 DPRINT ("BitmapBits == NULL??\n");
952 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
956 BITMAPOBJ_UnlockBitmap(hBitmap
);
962 NtGdiSetBitmapDimensionEx(
970 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
978 *Size
= bmp
->dimension
;
980 bmp
->dimension
.cx
= Width
;
981 bmp
->dimension
.cy
= Height
;
983 BITMAPOBJ_UnlockBitmap (hBitmap
);
995 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
996 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1000 return ((COLORREF
) -1);
1010 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1013 if (NewBrush
== NULL
)
1015 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1016 if (OldBrush
== NULL
)
1018 NtGdiDeleteObject(NewBrush
);
1021 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1022 NtGdiSelectObject(hDC
, OldBrush
);
1023 NtGdiDeleteObject(NewBrush
);
1043 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1047 PPALGDI PalDestGDI
, PalSourceGDI
;
1048 XLATEOBJ
*XlateObj
= NULL
;
1049 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1050 ULONG SourceMode
, DestMode
;
1051 PGDIBRUSHOBJ BrushObj
;
1052 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1053 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1055 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1057 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1060 DCDest
= DC_LockDc(hDCDest
);
1063 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1064 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1070 if (hDCSrc
!= hDCDest
)
1072 DCSrc
= DC_LockDc(hDCSrc
);
1075 DC_UnlockDc(hDCDest
);
1076 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1077 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1091 /* Offset the destination and source by the origin of their DCs. */
1092 XOriginDest
+= DCDest
->w
.DCOrgX
;
1093 YOriginDest
+= DCDest
->w
.DCOrgY
;
1096 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1097 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1100 DestRect
.left
= XOriginDest
;
1101 DestRect
.top
= YOriginDest
;
1102 DestRect
.right
= XOriginDest
+WidthDest
;
1103 DestRect
.bottom
= YOriginDest
+HeightDest
;
1105 SourceRect
.left
= XOriginSrc
;
1106 SourceRect
.top
= YOriginSrc
;
1107 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1108 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1110 /* Determine surfaces to be used in the bitblt */
1111 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1114 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1115 BitmapSrc
= BitmapDest
;
1117 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1126 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1127 if (NULL
== BrushObj
)
1129 if (UsesSource
&& hDCSrc
!= hDCDest
)
1131 DC_UnlockDc(hDCSrc
);
1133 DC_UnlockDc(hDCDest
);
1134 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1143 if (DCDest
->w
.hPalette
!= 0)
1144 DestPalette
= DCDest
->w
.hPalette
;
1146 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
1147 SourcePalette
= DCSrc
->w
.hPalette
;
1149 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
1150 if (NULL
== PalSourceGDI
)
1152 if (UsesSource
&& hDCSrc
!= hDCDest
)
1154 DC_UnlockDc(hDCSrc
);
1156 DC_UnlockDc(hDCDest
);
1157 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1160 SourceMode
= PalSourceGDI
->Mode
;
1161 PALETTE_UnlockPalette(SourcePalette
);
1163 if (DestPalette
== SourcePalette
)
1165 DestMode
= SourceMode
;
1169 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
1170 if (NULL
== PalDestGDI
)
1172 if (UsesSource
&& hDCSrc
!= hDCDest
)
1174 DC_UnlockDc(hDCSrc
);
1176 DC_UnlockDc(hDCDest
);
1177 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1180 DestMode
= PalDestGDI
->Mode
;
1181 PALETTE_UnlockPalette(DestPalette
);
1184 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
1185 if (NULL
== XlateObj
)
1187 if (UsesSource
&& hDCSrc
!= hDCDest
)
1189 DC_UnlockDc(hDCSrc
);
1191 DC_UnlockDc(hDCDest
);
1192 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1196 /* Perform the bitblt operation */
1197 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1198 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1200 EngDeleteXlate(XlateObj
);
1201 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1202 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1204 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1208 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1210 if (UsesSource
&& hDCSrc
!= hDCDest
)
1212 DC_UnlockDc(hDCSrc
);
1214 DC_UnlockDc(hDCDest
);
1219 /* Internal Functions */
1222 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1228 return 2 * ((bmWidth
+15) >> 4);
1231 bmWidth
*= 3; /* fall through */
1233 return bmWidth
+ (bmWidth
& 1);
1243 return 2 * ((bmWidth
+3) >> 2);
1252 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1256 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1261 if (IntGdiGetObject(hBitmap
, sizeof(BITMAP
), &bm
) == 0)
1266 res
= NtGdiCreateBitmapIndirect(&bm
);
1271 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* bm
.bmHeight
, TAG_BITMAP
);
1272 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1273 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1281 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1285 if(count
< (INT
) sizeof(DIBSECTION
))
1287 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1291 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1293 memcpy(buffer
, bmp
->dib
, count
);
1299 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1301 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1302 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1303 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1304 Bitmap
.bmPlanes
= 1;
1305 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1306 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1307 memcpy(buffer
, &Bitmap
, count
);