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(DCDest
->w
.hBitmap
);
146 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
148 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
150 DC_UnlockDc(hDCDest
);
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
)
196 DC_UnlockDc(hDCDest
);
197 if(BitmapDest
!= NULL
)
199 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
201 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
203 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
207 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
209 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
215 /* Perform the bitblt operation */
216 Status
= IntEngBitBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
217 &DestRect
, &SourcePoint
, NULL
, BrushObj
? &BrushInst
.BrushObject
: NULL
,
218 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
220 if (UsesSource
&& XlateObj
!= NULL
)
221 EngDeleteXlate(XlateObj
);
223 if(BitmapDest
!= NULL
)
225 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
227 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
229 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
231 if (BrushObj
!= NULL
)
233 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
235 if (UsesSource
&& hDCSrc
!= hDCDest
)
239 DC_UnlockDc(hDCDest
);
260 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
262 HPALETTE SourcePalette
= 0, DestPalette
= 0;
263 PPALGDI PalDestGDI
, PalSourceGDI
;
264 USHORT PalDestMode
, PalSrcMode
;
265 ULONG TransparentColor
= 0;
268 if(!(DCDest
= DC_LockDc(hdcDst
)))
270 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
271 SetLastWin32Error(ERROR_INVALID_HANDLE
);
277 /* Yes, Windows really returns TRUE in this case */
281 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
284 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
285 SetLastWin32Error(ERROR_INVALID_HANDLE
);
299 /* Yes, Windows really returns TRUE in this case */
303 /* Offset positions */
304 xDst
+= DCDest
->w
.DCOrgX
;
305 yDst
+= DCDest
->w
.DCOrgY
;
306 xSrc
+= DCSrc
->w
.DCOrgX
;
307 ySrc
+= DCSrc
->w
.DCOrgY
;
309 if(DCDest
->w
.hPalette
)
310 DestPalette
= DCDest
->w
.hPalette
;
312 if(DCSrc
->w
.hPalette
)
313 SourcePalette
= DCSrc
->w
.hPalette
;
315 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
319 SetLastWin32Error(ERROR_INVALID_HANDLE
);
322 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
324 PALETTE_UnlockPalette(SourcePalette
);
327 SetLastWin32Error(ERROR_INVALID_HANDLE
);
330 if(DestPalette
!= SourcePalette
)
332 PalDestMode
= PalDestGDI
->Mode
;
333 PalSrcMode
= PalSourceGDI
->Mode
;
334 PALETTE_UnlockPalette(DestPalette
);
338 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
340 PALETTE_UnlockPalette(SourcePalette
);
342 /* Translate Transparent (RGB) Color to the source palette */
343 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
345 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
346 EngDeleteXlate(XlateObj
);
349 /* Create the XLATE object to convert colors between source and destination */
350 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
352 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
353 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
355 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
356 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
361 rcDest
.right
= rcDest
.left
+ cxDst
;
362 rcDest
.bottom
= rcDest
.top
+ cyDst
;
365 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
366 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
368 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
370 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
374 Ret
= IntEngTransparentBlt(BitmapDest
, BitmapSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
375 TransparentColor
, 0);
378 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
379 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
387 EngDeleteXlate(XlateObj
);
404 /* NOTE: Windows also doesn't store nr. of planes separately! */
405 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
407 /* Check parameters */
408 if (!Height
|| !Width
)
410 Size
.cx
= Size
.cy
= 1;
414 Size
.cx
= abs(Width
);
415 Size
.cy
= abs(Height
);
418 /* Create the bitmap object. */
419 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
420 BitmapFormat(BitsPerPel
, BI_RGB
),
421 (Height
< 0 ? BMF_TOPDOWN
: 0) |
422 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
425 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
429 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
430 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
432 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
433 /* FIXME - bmp can be NULL!!!!!! */
434 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
435 BITMAPOBJ_UnlockBitmap( hBitmap
);
438 * NOTE: It's ugly practice, but we are using the object even
439 * after unlocking. Since the handle is currently known only
440 * to us it should be safe.
445 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
452 BITMAP_Cleanup(PVOID ObjectBody
)
454 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
455 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
456 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
458 if (pBmp
->dib
== NULL
)
460 ExFreePool(pBmp
->SurfObj
.pvBits
);
464 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
473 IntCreateCompatibleBitmap(
482 if ((Width
>= 0x10000) || (Height
>= 0x10000))
484 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
488 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
489 if (0 == Width
|| 0 == Height
)
491 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
495 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
502 NtGdiCreateCompatibleBitmap(
512 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
516 SetLastWin32Error(ERROR_INVALID_HANDLE
);
520 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
522 DPRINT ("\t\t%04x\n", Bmp
);
528 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
530 return NtGdiCreateBitmap (BM
->bmWidth
,
538 NtGdiCreateDiscardableBitmap(
543 /* FIXME: this probably should do something else */
544 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
566 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
570 NtGdiGetBitmapDimensionEx(
576 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
582 *Dimension
= bmp
->dimension
;
584 BITMAPOBJ_UnlockBitmap(hBitmap
);
590 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
593 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
594 BOOL bInRect
= FALSE
;
595 BITMAPOBJ
*BitmapObject
;
596 SURFOBJ
*SurfaceObject
;
600 dc
= DC_LockDc (hDC
);
604 SetLastWin32Error(ERROR_INVALID_HANDLE
);
612 XPos
+= dc
->w
.DCOrgX
;
613 YPos
+= dc
->w
.DCOrgY
;
614 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
617 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
618 SurfaceObject
= &BitmapObject
->SurfObj
;
621 if ( dc
->w
.hPalette
!= 0 )
622 Pal
= dc
->w
.hPalette
;
623 /* FIXME: Verify if it shouldn't be PAL_BGR! */
624 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
627 // check if this DC has a DIB behind it...
628 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
630 ASSERT ( SurfaceObject
->lDelta
);
631 Result
= XLATEOBJ_iXlate(XlateObj
,
632 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
634 EngDeleteXlate(XlateObj
);
636 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
641 // if Result is still CLR_INVALID, then the "quick" method above didn't work
642 if ( bInRect
&& Result
== CLR_INVALID
)
644 // FIXME: create a 1x1 32BPP DIB, and blit to it
645 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
648 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
650 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
651 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
652 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
655 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
660 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
661 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
663 // our bitmap is no longer selected, so we can access it's stuff...
664 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
667 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
668 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
671 NtGdiDeleteObject ( hBmpTmp
);
673 NtGdiDeleteDC ( hDCTmp
);
680 /***********************************************************************
682 * Ported from WINE by sedwards 11-4-03
684 * Someone thought it would be faster to do it here and then switch back
685 * to GDI32. I dunno. Write a test and let me know.
689 SwapROP3_SrcDst(BYTE bRop3
)
691 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
694 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
695 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
696 #define DSTCOPY 0x00AA0029
697 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
701 HDC hdcDest
, INT nXDest
, INT nYDest
,
702 INT nWidth
, INT nHeight
, HDC hdcSrc
,
703 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
704 INT xMask
, INT yMask
, DWORD dwRop
)
706 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
707 HDC hDCMask
, hDC1
, hDC2
;
708 static const DWORD ROP3Table
[256] =
710 0x00000042, 0x00010289,
711 0x00020C89, 0x000300AA,
712 0x00040C88, 0x000500A9,
713 0x00060865, 0x000702C5,
714 0x00080F08, 0x00090245,
715 0x000A0329, 0x000B0B2A,
716 0x000C0324, 0x000D0B25,
717 0x000E08A5, 0x000F0001,
718 0x00100C85, 0x001100A6,
719 0x00120868, 0x001302C8,
720 0x00140869, 0x001502C9,
721 0x00165CCA, 0x00171D54,
722 0x00180D59, 0x00191CC8,
723 0x001A06C5, 0x001B0768,
724 0x001C06CA, 0x001D0766,
725 0x001E01A5, 0x001F0385,
726 0x00200F09, 0x00210248,
727 0x00220326, 0x00230B24,
728 0x00240D55, 0x00251CC5,
729 0x002606C8, 0x00271868,
730 0x00280369, 0x002916CA,
731 0x002A0CC9, 0x002B1D58,
732 0x002C0784, 0x002D060A,
733 0x002E064A, 0x002F0E2A,
734 0x0030032A, 0x00310B28,
735 0x00320688, 0x00330008,
736 0x003406C4, 0x00351864,
737 0x003601A8, 0x00370388,
738 0x0038078A, 0x00390604,
739 0x003A0644, 0x003B0E24,
740 0x003C004A, 0x003D18A4,
741 0x003E1B24, 0x003F00EA,
742 0x00400F0A, 0x00410249,
743 0x00420D5D, 0x00431CC4,
744 0x00440328, 0x00450B29,
745 0x004606C6, 0x0047076A,
746 0x00480368, 0x004916C5,
747 0x004A0789, 0x004B0605,
748 0x004C0CC8, 0x004D1954,
749 0x004E0645, 0x004F0E25,
750 0x00500325, 0x00510B26,
751 0x005206C9, 0x00530764,
752 0x005408A9, 0x00550009,
753 0x005601A9, 0x00570389,
754 0x00580785, 0x00590609,
755 0x005A0049, 0x005B18A9,
756 0x005C0649, 0x005D0E29,
757 0x005E1B29, 0x005F00E9,
758 0x00600365, 0x006116C6,
759 0x00620786, 0x00630608,
760 0x00640788, 0x00650606,
761 0x00660046, 0x006718A8,
762 0x006858A6, 0x00690145,
763 0x006A01E9, 0x006B178A,
764 0x006C01E8, 0x006D1785,
765 0x006E1E28, 0x006F0C65,
766 0x00700CC5, 0x00711D5C,
767 0x00720648, 0x00730E28,
768 0x00740646, 0x00750E26,
769 0x00761B28, 0x007700E6,
770 0x007801E5, 0x00791786,
771 0x007A1E29, 0x007B0C68,
772 0x007C1E24, 0x007D0C69,
773 0x007E0955, 0x007F03C9,
774 0x008003E9, 0x00810975,
775 0x00820C49, 0x00831E04,
776 0x00840C48, 0x00851E05,
777 0x008617A6, 0x008701C5,
778 0x008800C6, 0x00891B08,
779 0x008A0E06, 0x008B0666,
780 0x008C0E08, 0x008D0668,
781 0x008E1D7C, 0x008F0CE5,
782 0x00900C45, 0x00911E08,
783 0x009217A9, 0x009301C4,
784 0x009417AA, 0x009501C9,
785 0x00960169, 0x0097588A,
786 0x00981888, 0x00990066,
787 0x009A0709, 0x009B07A8,
788 0x009C0704, 0x009D07A6,
789 0x009E16E6, 0x009F0345,
790 0x00A000C9, 0x00A11B05,
791 0x00A20E09, 0x00A30669,
792 0x00A41885, 0x00A50065,
793 0x00A60706, 0x00A707A5,
794 0x00A803A9, 0x00A90189,
795 0x00AA0029, 0x00AB0889,
796 0x00AC0744, 0x00AD06E9,
797 0x00AE0B06, 0x00AF0229,
798 0x00B00E05, 0x00B10665,
799 0x00B21974, 0x00B30CE8,
800 0x00B4070A, 0x00B507A9,
801 0x00B616E9, 0x00B70348,
802 0x00B8074A, 0x00B906E6,
803 0x00BA0B09, 0x00BB0226,
804 0x00BC1CE4, 0x00BD0D7D,
805 0x00BE0269, 0x00BF08C9,
806 0x00C000CA, 0x00C11B04,
807 0x00C21884, 0x00C3006A,
808 0x00C40E04, 0x00C50664,
809 0x00C60708, 0x00C707AA,
810 0x00C803A8, 0x00C90184,
811 0x00CA0749, 0x00CB06E4,
812 0x00CC0020, 0x00CD0888,
813 0x00CE0B08, 0x00CF0224,
814 0x00D00E0A, 0x00D1066A,
815 0x00D20705, 0x00D307A4,
816 0x00D41D78, 0x00D50CE9,
817 0x00D616EA, 0x00D70349,
818 0x00D80745, 0x00D906E8,
819 0x00DA1CE9, 0x00DB0D75,
820 0x00DC0B04, 0x00DD0228,
821 0x00DE0268, 0x00DF08C8,
822 0x00E003A5, 0x00E10185,
823 0x00E20746, 0x00E306EA,
824 0x00E40748, 0x00E506E5,
825 0x00E61CE8, 0x00E70D79,
826 0x00E81D74, 0x00E95CE6,
827 0x00EA02E9, 0x00EB0849,
828 0x00EC02E8, 0x00ED0848,
829 0x00EE0086, 0x00EF0A08,
830 0x00F00021, 0x00F10885,
831 0x00F20B05, 0x00F3022A,
832 0x00F40B0A, 0x00F50225,
833 0x00F60265, 0x00F708C5,
834 0x00F802E5, 0x00F90845,
835 0x00FA0089, 0x00FB0A09,
836 0x00FC008A, 0x00FD0A0A,
837 0x00FE02A9, 0x00FF0062,
841 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
843 /* 1. make mask bitmap's dc */
844 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
845 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
847 /* 2. make masked Background bitmap */
849 /* 2.1 make bitmap */
850 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
851 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
852 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
854 /* 2.2 draw dest bitmap and mask */
855 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
856 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
857 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
859 /* 3. make masked Foreground bitmap */
861 /* 3.1 make bitmap */
862 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
863 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
864 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
866 /* 3.2 draw src bitmap and mask */
867 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
868 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
869 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
871 /* 4. combine two bitmap and copy it to hdcDest */
872 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
873 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
875 /* 5. restore all object */
876 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
877 NtGdiSelectObject(hDC1
, hOldBitmap2
);
878 NtGdiSelectObject(hDC2
, hOldBitmap3
);
880 /* 6. delete all temp object */
881 NtGdiDeleteObject(hBitmap2
);
882 NtGdiDeleteObject(hBitmap3
);
886 NtGdiDeleteDC(hDCMask
);
917 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
918 if (bmp
== NULL
|| Bits
== NULL
)
925 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
929 /* Only get entire lines */
930 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
931 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
933 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
935 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
936 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
940 bmp
->SurfObj
.sizlBitmap
.cx
,
941 bmp
->SurfObj
.sizlBitmap
.cy
,
942 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
946 /* FIXME: call DDI specific function here if available */
949 DPRINT ("Calling device specific BitmapBits\n");
950 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
952 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
956 DPRINT ("BitmapBits == NULL??\n");
963 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
967 BITMAPOBJ_UnlockBitmap(hBitmap
);
973 NtGdiSetBitmapDimensionEx(
981 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
989 *Size
= bmp
->dimension
;
991 bmp
->dimension
.cx
= Width
;
992 bmp
->dimension
.cy
= Height
;
994 BITMAPOBJ_UnlockBitmap (hBitmap
);
1006 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
1007 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1011 return ((COLORREF
) -1);
1021 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1024 if (NewBrush
== NULL
)
1026 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1027 if (OldBrush
== NULL
)
1029 NtGdiDeleteObject(NewBrush
);
1032 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1033 NtGdiSelectObject(hDC
, OldBrush
);
1034 NtGdiDeleteObject(NewBrush
);
1054 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1058 XLATEOBJ
*XlateObj
= NULL
;
1059 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1060 PGDIBRUSHOBJ BrushObj
;
1061 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1062 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1064 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1066 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1069 DCDest
= DC_LockDc(hDCDest
);
1072 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1073 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1078 DC_UnlockDc(hDCDest
);
1079 /* Yes, Windows really returns TRUE in this case */
1085 if (hDCSrc
!= hDCDest
)
1087 DCSrc
= DC_LockDc(hDCSrc
);
1090 DC_UnlockDc(hDCDest
);
1091 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1092 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1097 DC_UnlockDc(hDCSrc
);
1098 DC_UnlockDc(hDCDest
);
1099 /* Yes, Windows really returns TRUE in this case */
1113 /* Offset the destination and source by the origin of their DCs. */
1114 XOriginDest
+= DCDest
->w
.DCOrgX
;
1115 YOriginDest
+= DCDest
->w
.DCOrgY
;
1118 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1119 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1122 DestRect
.left
= XOriginDest
;
1123 DestRect
.top
= YOriginDest
;
1124 DestRect
.right
= XOriginDest
+WidthDest
;
1125 DestRect
.bottom
= YOriginDest
+HeightDest
;
1127 SourceRect
.left
= XOriginSrc
;
1128 SourceRect
.top
= YOriginSrc
;
1129 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1130 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1132 /* Determine surfaces to be used in the bitblt */
1133 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1136 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1137 BitmapSrc
= BitmapDest
;
1139 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1148 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1149 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1150 if ( SourceRect
.left
< 0 )
1152 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1153 SourceRect
.left
= 0;
1155 if ( SourceRect
.top
< 0 )
1157 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1160 if ( SourceRect
.right
< -1 )
1162 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1163 SourceRect
.right
= -1;
1165 if ( SourceRect
.bottom
< -1 )
1167 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1168 SourceRect
.bottom
= -1;
1170 if ( SourceRect
.right
> sw
)
1172 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1173 SourceRect
.right
= sw
;
1175 if ( SourceRect
.bottom
> sh
)
1177 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1178 SourceRect
.bottom
= sh
;
1182 if ( SourceRect
.left
> sw
)
1184 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1185 SourceRect
.left
= 0;
1187 if ( SourceRect
.top
> sh
)
1189 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1192 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1194 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1202 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1203 if (NULL
== BrushObj
)
1205 if (UsesSource
&& hDCSrc
!= hDCDest
)
1207 DC_UnlockDc(hDCSrc
);
1209 DC_UnlockDc(hDCDest
);
1210 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1219 /* Create the XLATEOBJ. */
1222 if (DCDest
->w
.hPalette
!= 0)
1223 DestPalette
= DCDest
->w
.hPalette
;
1225 if (DCSrc
->w
.hPalette
!= 0)
1226 SourcePalette
= DCSrc
->w
.hPalette
;
1228 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1229 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1230 if (NULL
== XlateObj
)
1232 if (UsesSource
&& hDCSrc
!= hDCDest
)
1234 DC_UnlockDc(hDCSrc
);
1236 DC_UnlockDc(hDCDest
);
1237 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1242 /* Perform the bitblt operation */
1243 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1244 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1247 EngDeleteXlate(XlateObj
);
1250 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1253 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1255 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1257 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1258 if (UsesSource
&& hDCSrc
!= hDCDest
)
1260 DC_UnlockDc(hDCSrc
);
1262 DC_UnlockDc(hDCDest
);
1267 /* Internal Functions */
1270 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1276 return 2 * ((bmWidth
+15) >> 4);
1279 bmWidth
*= 3; /* fall through */
1281 return bmWidth
+ (bmWidth
& 1);
1291 return 2 * ((bmWidth
+3) >> 2);
1300 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1304 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1310 if (hBitmap
== NULL
)
1313 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1317 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1319 if (Bitmap
->SurfObj
.lDelta
>= 0)
1320 bm
.bmHeight
= -bm
.bmHeight
;
1322 res
= NtGdiCreateBitmapIndirect(&bm
);
1327 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1328 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1329 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1333 GDIOBJ_UnlockObj(hBitmap
);
1339 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1343 if(count
< (INT
) sizeof(DIBSECTION
))
1345 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1349 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1351 memcpy(buffer
, bmp
->dib
, count
);
1357 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1359 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1360 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1361 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1362 Bitmap
.bmPlanes
= 1;
1363 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1364 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1365 memcpy(buffer
, &Bitmap
, count
);