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.66 2004/04/03 21:25:20 weiden Exp $ */
20 #undef WIN32_LEAN_AND_MEAN
23 #include <win32k/color.h>
24 #include <win32k/gdiobj.h>
25 #include <win32k/bitmaps.h>
26 #include <win32k/brush.h>
27 #include <win32k/region.h>
28 //#include <win32k/debug.h>
29 #include "../eng/handle.h"
30 #include <include/inteng.h>
31 #include <include/intgdi.h>
32 #include <include/eng.h>
33 #include <include/error.h>
34 #include <include/surface.h>
35 #include <include/palette.h>
36 #include <include/tags.h>
37 #include <rosrtl/gdimacro.h>
40 #include <win32k/debug1.h>
56 PSURFOBJ SurfDest
, SurfSrc
;
57 PSURFGDI SurfGDIDest
, SurfGDISrc
;
61 PPALGDI PalDestGDI
, PalSourceGDI
;
62 PXLATEOBJ XlateObj
= NULL
;
63 HPALETTE SourcePalette
, DestPalette
;
64 ULONG SourceMode
, DestMode
;
66 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
67 BOOL UsesPattern
= TRUE
;//((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
70 DCDest
= DC_LockDc(hDCDest
);
73 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
74 SetLastWin32Error(ERROR_INVALID_HANDLE
);
80 if (hDCSrc
!= hDCDest
)
82 DCSrc
= DC_LockDc(hDCSrc
);
86 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
87 SetLastWin32Error(ERROR_INVALID_HANDLE
);
101 /* Offset the destination and source by the origin of their DCs. */
102 XDest
+= DCDest
->w
.DCOrgX
;
103 YDest
+= DCDest
->w
.DCOrgY
;
106 XSrc
+= DCSrc
->w
.DCOrgX
;
107 YSrc
+= DCSrc
->w
.DCOrgY
;
110 DestRect
.left
= XDest
;
111 DestRect
.top
= YDest
;
112 DestRect
.right
= XDest
+Width
;
113 DestRect
.bottom
= YDest
+Height
;
115 SourcePoint
.x
= XSrc
;
116 SourcePoint
.y
= YSrc
;
118 /* Determine surfaces to be used in the bitblt */
119 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
120 SurfGDIDest
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfDest
);
123 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
124 SurfGDISrc
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfSrc
);
134 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
135 if (NULL
== BrushObj
)
137 if (UsesSource
&& hDCSrc
!= hDCDest
)
141 DC_UnlockDc(hDCDest
);
142 SetLastWin32Error(ERROR_INVALID_HANDLE
);
151 if (DCDest
->w
.hPalette
!= 0)
153 DestPalette
= DCDest
->w
.hPalette
;
157 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
160 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
162 SourcePalette
= DCSrc
->w
.hPalette
;
166 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
169 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
170 if (NULL
== PalSourceGDI
)
172 if (UsesSource
&& hDCSrc
!= hDCDest
)
176 DC_UnlockDc(hDCDest
);
177 SetLastWin32Error(ERROR_INVALID_HANDLE
);
180 SourceMode
= PalSourceGDI
->Mode
;
181 PALETTE_UnlockPalette(SourcePalette
);
183 if (DestPalette
== SourcePalette
)
185 DestMode
= SourceMode
;
189 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
190 if (NULL
== PalDestGDI
)
192 if (UsesSource
&& hDCSrc
!= hDCDest
)
196 DC_UnlockDc(hDCDest
);
197 SetLastWin32Error(ERROR_INVALID_HANDLE
);
200 DestMode
= PalDestGDI
->Mode
;
201 PALETTE_UnlockPalette(DestPalette
);
204 /* KB41464 details how to convert between mono and color */
205 if (DCDest
->w
.bitsPerPixel
== 1)
207 XlateObj
= (PXLATEOBJ
)IntEngCreateMonoXlate(SourceMode
, DestPalette
,
208 SourcePalette
, DCSrc
->w
.backgroundColor
);
210 else if (UsesSource
&& 1 == DCSrc
->w
.bitsPerPixel
)
214 Colors
[0] = DCSrc
->w
.textColor
;
215 Colors
[1] = DCSrc
->w
.backgroundColor
;
216 Mono
= EngCreatePalette(PAL_INDEXED
, 2, Colors
, 0, 0, 0);
219 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, PAL_INDEXED
, DestPalette
, Mono
);
228 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
230 if (NULL
== XlateObj
)
234 EngDeletePalette(Mono
);
236 if (UsesSource
&& hDCSrc
!= hDCDest
)
240 DC_UnlockDc(hDCDest
);
241 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
245 /* Perform the bitblt operation */
246 Status
= IntEngBitBlt(SurfDest
, SurfSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
247 &DestRect
, &SourcePoint
, NULL
, BrushObj
, NULL
, ROP
);
249 EngDeleteXlate(XlateObj
);
252 EngDeletePalette(Mono
);
256 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
258 if (UsesSource
&& hDCSrc
!= hDCDest
)
262 DC_UnlockDc(hDCDest
);
283 PSURFOBJ SurfDest
, SurfSrc
;
285 HPALETTE SourcePalette
, DestPalette
;
286 PPALGDI PalDestGDI
, PalSourceGDI
;
287 USHORT PalDestMode
, PalSrcMode
;
288 ULONG TransparentColor
;
291 if(!(DCDest
= DC_LockDc(hdcDst
)))
293 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
294 SetLastWin32Error(ERROR_INVALID_HANDLE
);
298 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
301 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
302 SetLastWin32Error(ERROR_INVALID_HANDLE
);
310 if(DCDest
->w
.hPalette
)
311 DestPalette
= DCDest
->w
.hPalette
;
313 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
315 if(DCSrc
->w
.hPalette
)
316 SourcePalette
= DCSrc
->w
.hPalette
;
318 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
320 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
324 SetLastWin32Error(ERROR_INVALID_HANDLE
);
327 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
329 PALETTE_UnlockPalette(SourcePalette
);
332 SetLastWin32Error(ERROR_INVALID_HANDLE
);
335 if(DestPalette
!= SourcePalette
)
337 PalDestMode
= PalDestGDI
->Mode
;
338 PalSrcMode
= PalSourceGDI
->Mode
;
339 PALETTE_UnlockPalette(DestPalette
);
343 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
345 PALETTE_UnlockPalette(SourcePalette
);
347 if((XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
)))
349 /* FIXME - is color translation right? */
350 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
354 /* FIXME - what should be done here? */
355 TransparentColor
= (ULONG
)TransColor
;
358 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
360 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
365 rcDest
.right
= rcDest
.left
+ cxDst
;
366 rcDest
.bottom
= rcDest
.top
+ cyDst
;
369 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
370 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
372 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
374 /* FIXME - Create a temporary bitmap and stretchblt it */
375 DPRINT1("TransparentBlt() does not support stretching!\n");
379 Ret
= IntTransparentBlt(SurfDest
, SurfSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
380 TransparentColor
, 0);
390 EngDeleteXlate(XlateObj
);
406 Planes
= (BYTE
) Planes
;
407 BitsPerPel
= (BYTE
) BitsPerPel
;
409 /* Check parameters */
410 if (!Height
|| !Width
)
417 DPRINT("NtGdiCreateBitmap - UNIMPLEMENTED\n");
429 /* Create the BITMAPOBJ */
430 hBitmap
= BITMAPOBJ_AllocBitmap ();
433 DPRINT("NtGdiCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n");
437 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
439 DPRINT("NtGdiCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width
, Height
,
440 1 << (Planes
* BitsPerPel
), BitsPerPel
, bmp
);
442 bmp
->dimension
.cx
= 0;
443 bmp
->dimension
.cy
= 0;
444 bmp
->bitmap
.bmType
= 0;
445 bmp
->bitmap
.bmWidth
= Width
;
446 bmp
->bitmap
.bmHeight
= Height
;
447 bmp
->bitmap
.bmPlanes
= Planes
;
448 bmp
->bitmap
.bmBitsPixel
= BitsPerPel
;
449 bmp
->bitmap
.bmWidthBytes
= BITMAPOBJ_GetWidthBytes (Width
, BitsPerPel
);
450 bmp
->bitmap
.bmBits
= NULL
;
451 bmp
->DDBitmap
= NULL
;
454 // Allocate memory for bitmap bits
455 bmp
->bitmap
.bmBits
= ExAllocatePoolWithTag(PagedPool
, bmp
->bitmap
.bmWidthBytes
* bmp
->bitmap
.bmHeight
, TAG_BITMAP
);
457 BITMAPOBJ_UnlockBitmap( hBitmap
);
459 if (Bits
) /* Set bitmap bits */
461 NtGdiSetBitmapBits(hBitmap
, Height
* bmp
->bitmap
.bmWidthBytes
, Bits
);
465 // Initialize the bitmap (fixes bug 244?)
466 RtlZeroMemory(bmp
->bitmap
.bmBits
, Height
* bmp
->bitmap
.bmWidthBytes
);
473 Bitmap_InternalDelete( PBITMAPOBJ pBmp
)
477 if (NULL
!= pBmp
->bitmap
.bmBits
)
479 if (NULL
!= pBmp
->dib
)
481 if (NULL
== pBmp
->dib
->dshSection
)
483 EngFreeUserMem(pBmp
->bitmap
.bmBits
);
487 /* This is a file-mapped section */
493 ExFreePool(pBmp
->bitmap
.bmBits
);
502 IntCreateCompatibleBitmap(
511 if ((Width
>= 0x10000) || (Height
>= 0x10000))
513 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
517 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
518 if (0 == Width
|| 0 == Height
)
520 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
524 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
531 NtGdiCreateCompatibleBitmap(
541 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, dc
->w
.bitsPerPixel
);
545 SetLastWin32Error(ERROR_INVALID_HANDLE
);
549 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
551 DPRINT ("\t\t%04x\n", Bmp
);
557 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
559 return NtGdiCreateBitmap (BM
->bmWidth
,
567 NtGdiCreateDiscardableBitmap(
572 /* FIXME: this probably should do something else */
573 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
594 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
598 NtGdiGetBitmapDimensionEx(
604 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
610 *Dimension
= bmp
->dimension
;
612 BITMAPOBJ_UnlockBitmap(hBitmap
);
618 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
621 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
622 BOOL bInRect
= FALSE
;
624 PSURFOBJ SurfaceObject
;
630 dc
= DC_LockDc (hDC
);
634 SetLastWin32Error(ERROR_INVALID_HANDLE
);
637 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
640 SurfaceObject
= (PSURFOBJ
)AccessUserObject((ULONG
)dc
->Surface
);
641 ASSERT(SurfaceObject
);
642 Surface
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfaceObject
);
645 if ( dc
->w
.hPalette
!= 0 )
646 Pal
= dc
->w
.hPalette
;
648 Pal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
649 PalGDI
= PALETTE_LockPalette(Pal
);
652 PalMode
= PalGDI
->Mode
;
653 PALETTE_UnlockPalette(Pal
);
655 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate ( PAL_RGB
, PalMode
, NULL
, Pal
);
658 // check if this DC has a DIB behind it...
659 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
661 ASSERT ( SurfaceObject
->lDelta
&& Surface
->DIB_GetPixel
);
662 Result
= XLATEOBJ_iXlate(XlateObj
, Surface
->DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
664 EngDeleteXlate(XlateObj
);
671 // if Result is still CLR_INVALID, then the "quick" method above didn't work
672 if ( bInRect
&& Result
== CLR_INVALID
)
674 // FIXME: create a 1x1 32BPP DIB, and blit to it
675 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
678 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
680 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
681 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
682 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
685 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
690 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
691 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
693 // our bitmap is no longer selected, so we can access it's stuff...
694 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
697 Result
= *(COLORREF
*)bmpobj
->bitmap
.bmBits
;
698 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
701 NtGdiDeleteObject ( hBmpTmp
);
703 NtGdiDeleteDC ( hDCTmp
);
710 /***********************************************************************
712 * Ported from WINE by sedwards 11-4-03
714 * Someone thought it would be faster to do it here and then switch back
715 * to GDI32. I dunno. Write a test and let me know.
719 SwapROP3_SrcDst(BYTE bRop3
)
721 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
724 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
725 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
726 #define DSTCOPY 0x00AA0029
727 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
731 HDC hdcDest
, INT nXDest
, INT nYDest
,
732 INT nWidth
, INT nHeight
, HDC hdcSrc
,
733 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
734 INT xMask
, INT yMask
, DWORD dwRop
)
736 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
737 HDC hDCMask
, hDC1
, hDC2
;
738 static const DWORD ROP3Table
[256] =
740 0x00000042, 0x00010289,
741 0x00020C89, 0x000300AA,
742 0x00040C88, 0x000500A9,
743 0x00060865, 0x000702C5,
744 0x00080F08, 0x00090245,
745 0x000A0329, 0x000B0B2A,
746 0x000C0324, 0x000D0B25,
747 0x000E08A5, 0x000F0001,
748 0x00100C85, 0x001100A6,
749 0x00120868, 0x001302C8,
750 0x00140869, 0x001502C9,
751 0x00165CCA, 0x00171D54,
752 0x00180D59, 0x00191CC8,
753 0x001A06C5, 0x001B0768,
754 0x001C06CA, 0x001D0766,
755 0x001E01A5, 0x001F0385,
756 0x00200F09, 0x00210248,
757 0x00220326, 0x00230B24,
758 0x00240D55, 0x00251CC5,
759 0x002606C8, 0x00271868,
760 0x00280369, 0x002916CA,
761 0x002A0CC9, 0x002B1D58,
762 0x002C0784, 0x002D060A,
763 0x002E064A, 0x002F0E2A,
764 0x0030032A, 0x00310B28,
765 0x00320688, 0x00330008,
766 0x003406C4, 0x00351864,
767 0x003601A8, 0x00370388,
768 0x0038078A, 0x00390604,
769 0x003A0644, 0x003B0E24,
770 0x003C004A, 0x003D18A4,
771 0x003E1B24, 0x003F00EA,
772 0x00400F0A, 0x00410249,
773 0x00420D5D, 0x00431CC4,
774 0x00440328, 0x00450B29,
775 0x004606C6, 0x0047076A,
776 0x00480368, 0x004916C5,
777 0x004A0789, 0x004B0605,
778 0x004C0CC8, 0x004D1954,
779 0x004E0645, 0x004F0E25,
780 0x00500325, 0x00510B26,
781 0x005206C9, 0x00530764,
782 0x005408A9, 0x00550009,
783 0x005601A9, 0x00570389,
784 0x00580785, 0x00590609,
785 0x005A0049, 0x005B18A9,
786 0x005C0649, 0x005D0E29,
787 0x005E1B29, 0x005F00E9,
788 0x00600365, 0x006116C6,
789 0x00620786, 0x00630608,
790 0x00640788, 0x00650606,
791 0x00660046, 0x006718A8,
792 0x006858A6, 0x00690145,
793 0x006A01E9, 0x006B178A,
794 0x006C01E8, 0x006D1785,
795 0x006E1E28, 0x006F0C65,
796 0x00700CC5, 0x00711D5C,
797 0x00720648, 0x00730E28,
798 0x00740646, 0x00750E26,
799 0x00761B28, 0x007700E6,
800 0x007801E5, 0x00791786,
801 0x007A1E29, 0x007B0C68,
802 0x007C1E24, 0x007D0C69,
803 0x007E0955, 0x007F03C9,
804 0x008003E9, 0x00810975,
805 0x00820C49, 0x00831E04,
806 0x00840C48, 0x00851E05,
807 0x008617A6, 0x008701C5,
808 0x008800C6, 0x00891B08,
809 0x008A0E06, 0x008B0666,
810 0x008C0E08, 0x008D0668,
811 0x008E1D7C, 0x008F0CE5,
812 0x00900C45, 0x00911E08,
813 0x009217A9, 0x009301C4,
814 0x009417AA, 0x009501C9,
815 0x00960169, 0x0097588A,
816 0x00981888, 0x00990066,
817 0x009A0709, 0x009B07A8,
818 0x009C0704, 0x009D07A6,
819 0x009E16E6, 0x009F0345,
820 0x00A000C9, 0x00A11B05,
821 0x00A20E09, 0x00A30669,
822 0x00A41885, 0x00A50065,
823 0x00A60706, 0x00A707A5,
824 0x00A803A9, 0x00A90189,
825 0x00AA0029, 0x00AB0889,
826 0x00AC0744, 0x00AD06E9,
827 0x00AE0B06, 0x00AF0229,
828 0x00B00E05, 0x00B10665,
829 0x00B21974, 0x00B30CE8,
830 0x00B4070A, 0x00B507A9,
831 0x00B616E9, 0x00B70348,
832 0x00B8074A, 0x00B906E6,
833 0x00BA0B09, 0x00BB0226,
834 0x00BC1CE4, 0x00BD0D7D,
835 0x00BE0269, 0x00BF08C9,
836 0x00C000CA, 0x00C11B04,
837 0x00C21884, 0x00C3006A,
838 0x00C40E04, 0x00C50664,
839 0x00C60708, 0x00C707AA,
840 0x00C803A8, 0x00C90184,
841 0x00CA0749, 0x00CB06E4,
842 0x00CC0020, 0x00CD0888,
843 0x00CE0B08, 0x00CF0224,
844 0x00D00E0A, 0x00D1066A,
845 0x00D20705, 0x00D307A4,
846 0x00D41D78, 0x00D50CE9,
847 0x00D616EA, 0x00D70349,
848 0x00D80745, 0x00D906E8,
849 0x00DA1CE9, 0x00DB0D75,
850 0x00DC0B04, 0x00DD0228,
851 0x00DE0268, 0x00DF08C8,
852 0x00E003A5, 0x00E10185,
853 0x00E20746, 0x00E306EA,
854 0x00E40748, 0x00E506E5,
855 0x00E61CE8, 0x00E70D79,
856 0x00E81D74, 0x00E95CE6,
857 0x00EA02E9, 0x00EB0849,
858 0x00EC02E8, 0x00ED0848,
859 0x00EE0086, 0x00EF0A08,
860 0x00F00021, 0x00F10885,
861 0x00F20B05, 0x00F3022A,
862 0x00F40B0A, 0x00F50225,
863 0x00F60265, 0x00F708C5,
864 0x00F802E5, 0x00F90845,
865 0x00FA0089, 0x00FB0A09,
866 0x00FC008A, 0x00FD0A0A,
867 0x00FE02A9, 0x00FF0062,
871 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
873 /* 1. make mask bitmap's dc */
874 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
875 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
877 /* 2. make masked Background bitmap */
879 /* 2.1 make bitmap */
880 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
881 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
882 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
884 /* 2.2 draw dest bitmap and mask */
885 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
886 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
887 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
889 /* 3. make masked Foreground bitmap */
891 /* 3.1 make bitmap */
892 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
893 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
894 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
896 /* 3.2 draw src bitmap and mask */
897 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
898 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
899 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
901 /* 4. combine two bitmap and copy it to hdcDest */
902 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
903 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
905 /* 5. restore all object */
906 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
907 NtGdiSelectObject(hDC1
, hOldBitmap2
);
908 NtGdiSelectObject(hDC2
, hOldBitmap3
);
910 /* 6. delete all temp object */
911 NtGdiDeleteObject(hBitmap2
);
912 NtGdiDeleteObject(hBitmap3
);
916 NtGdiDeleteDC(hDCMask
);
946 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
947 if (bmp
== NULL
|| Bits
== NULL
)
954 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
958 /* Only get entire lines */
959 height
= Bytes
/ bmp
->bitmap
.bmWidthBytes
;
960 if (height
> bmp
->bitmap
.bmHeight
)
962 height
= bmp
->bitmap
.bmHeight
;
964 Bytes
= height
* bmp
->bitmap
.bmWidthBytes
;
965 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
970 bmp
->bitmap
.bmHeight
,
971 1 << bmp
->bitmap
.bmBitsPixel
,
975 /* FIXME: call DDI specific function here if available */
978 DPRINT ("Calling device specific BitmapBits\n");
979 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
981 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
985 DPRINT ("BitmapBits == NULL??\n");
992 /* FIXME: Alloc enough for entire bitmap */
993 if (bmp
->bitmap
.bmBits
== NULL
)
995 bmp
->bitmap
.bmBits
= ExAllocatePoolWithTag(PagedPool
, Bytes
, TAG_BITMAP
);
997 if(!bmp
->bitmap
.bmBits
)
999 DPRINT ("Unable to allocate bit buffer\n");
1004 memcpy(bmp
->bitmap
.bmBits
, Bits
, Bytes
);
1009 BITMAPOBJ_UnlockBitmap(hBitmap
);
1015 NtGdiSetBitmapDimensionEx(
1023 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1031 *Size
= bmp
->dimension
;
1033 bmp
->dimension
.cx
= Width
;
1034 bmp
->dimension
.cy
= Height
;
1036 BITMAPOBJ_UnlockBitmap (hBitmap
);
1048 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
1049 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1053 return ((COLORREF
) -1);
1063 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1066 if (NewBrush
== NULL
)
1068 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1069 if (OldBrush
== NULL
)
1071 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1072 NtGdiSelectObject(hDC
, OldBrush
);
1073 NtGdiDeleteObject(NewBrush
);
1093 PSURFOBJ SurfDest
, SurfSrc
;
1094 PSURFGDI SurfGDIDest
, SurfGDISrc
;
1098 PPALGDI PalDestGDI
, PalSourceGDI
;
1099 PXLATEOBJ XlateObj
= NULL
;
1100 HPALETTE SourcePalette
, DestPalette
;
1101 ULONG SourceMode
, DestMode
;
1103 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1104 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1106 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1108 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1111 DCDest
= DC_LockDc(hDCDest
);
1114 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1115 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1121 if (hDCSrc
!= hDCDest
)
1123 DCSrc
= DC_LockDc(hDCSrc
);
1126 DC_UnlockDc(hDCDest
);
1127 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1128 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1142 /* Offset the destination and source by the origin of their DCs. */
1143 XOriginDest
+= DCDest
->w
.DCOrgX
;
1144 YOriginDest
+= DCDest
->w
.DCOrgY
;
1147 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1148 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1151 DestRect
.left
= XOriginDest
;
1152 DestRect
.top
= YOriginDest
;
1153 DestRect
.right
= XOriginDest
+WidthDest
;
1154 DestRect
.bottom
= YOriginDest
+HeightDest
;
1156 SourceRect
.left
= XOriginSrc
;
1157 SourceRect
.top
= YOriginSrc
;
1158 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1159 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1161 /* Determine surfaces to be used in the bitblt */
1162 SurfDest
= (PSURFOBJ
)AccessUserObject((ULONG
)DCDest
->Surface
);
1163 SurfGDIDest
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfDest
);
1166 SurfSrc
= (PSURFOBJ
)AccessUserObject((ULONG
)DCSrc
->Surface
);
1167 SurfGDISrc
= (PSURFGDI
)AccessInternalObjectFromUserObject(SurfSrc
);
1177 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1178 if (NULL
== BrushObj
)
1180 if (UsesSource
&& hDCSrc
!= hDCDest
)
1182 DC_UnlockDc(hDCSrc
);
1184 DC_UnlockDc(hDCDest
);
1185 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1194 if (DCDest
->w
.hPalette
!= 0)
1196 DestPalette
= DCDest
->w
.hPalette
;
1200 DestPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
1203 if (UsesSource
&& DCSrc
->w
.hPalette
!= 0)
1205 SourcePalette
= DCSrc
->w
.hPalette
;
1209 SourcePalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
1212 PalSourceGDI
= PALETTE_LockPalette(SourcePalette
);
1213 if (NULL
== PalSourceGDI
)
1215 if (UsesSource
&& hDCSrc
!= hDCDest
)
1217 DC_UnlockDc(hDCSrc
);
1219 DC_UnlockDc(hDCDest
);
1220 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1223 SourceMode
= PalSourceGDI
->Mode
;
1224 PALETTE_UnlockPalette(SourcePalette
);
1226 if (DestPalette
== SourcePalette
)
1228 DestMode
= SourceMode
;
1232 PalDestGDI
= PALETTE_LockPalette(DestPalette
);
1233 if (NULL
== PalDestGDI
)
1235 if (UsesSource
&& hDCSrc
!= hDCDest
)
1237 DC_UnlockDc(hDCSrc
);
1239 DC_UnlockDc(hDCDest
);
1240 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1243 DestMode
= PalDestGDI
->Mode
;
1244 PALETTE_UnlockPalette(DestPalette
);
1247 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(DestMode
, SourceMode
, DestPalette
, SourcePalette
);
1248 if (NULL
== XlateObj
)
1250 if (UsesSource
&& hDCSrc
!= hDCDest
)
1252 DC_UnlockDc(hDCSrc
);
1254 DC_UnlockDc(hDCDest
);
1255 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1259 /* Perform the bitblt operation */
1260 Status
= IntEngStretchBlt(SurfDest
, SurfSrc
, NULL
, DCDest
->CombinedClip
,
1261 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1263 EngDeleteXlate(XlateObj
);
1266 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1268 if (UsesSource
&& hDCSrc
!= hDCDest
)
1270 DC_UnlockDc(hDCSrc
);
1272 DC_UnlockDc(hDCDest
);
1277 /* Internal Functions */
1280 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1286 return 2 * ((bmWidth
+15) >> 4);
1289 bmWidth
*= 3; /* fall through */
1291 return bmWidth
+ (bmWidth
& 1);
1301 return 2 * ((bmWidth
+3) >> 2);
1310 return ((bmWidth
* bpp
+ 31) & ~31) >> 3;
1314 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1320 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1329 BITMAPOBJ_UnlockBitmap(hBitmap
);
1330 res
= NtGdiCreateBitmapIndirect(&bm
);
1335 buf
= ExAllocatePoolWithTag (NonPagedPool
, bm
.bmWidthBytes
* bm
.bmHeight
, TAG_BITMAP
);
1336 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1337 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1345 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1349 if(count
< (INT
) sizeof(DIBSECTION
))
1351 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1355 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1357 memcpy(buffer
, bmp
->dib
, count
);
1362 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1363 memcpy(buffer
, &bmp
->bitmap
, count
);