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
);
466 if (pBmp
->hDIBPalette
)
468 NtGdiDeleteObject(pBmp
->hDIBPalette
);
477 IntCreateCompatibleBitmap(
486 if ((Width
>= 0x10000) || (Height
>= 0x10000))
488 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
492 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
493 if (0 == Width
|| 0 == Height
)
495 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
499 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
506 NtGdiCreateCompatibleBitmap(
516 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
520 SetLastWin32Error(ERROR_INVALID_HANDLE
);
524 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
526 DPRINT ("\t\t%04x\n", Bmp
);
532 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
534 return NtGdiCreateBitmap (BM
->bmWidth
,
542 NtGdiCreateDiscardableBitmap(
547 /* FIXME: this probably should do something else */
548 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
559 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
561 /* lie and say we succeded */
572 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
576 NtGdiGetBitmapDimensionEx(
582 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
588 *Dimension
= bmp
->dimension
;
590 BITMAPOBJ_UnlockBitmap(hBitmap
);
596 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
599 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
600 BOOL bInRect
= FALSE
;
601 BITMAPOBJ
*BitmapObject
;
602 SURFOBJ
*SurfaceObject
;
606 dc
= DC_LockDc (hDC
);
610 SetLastWin32Error(ERROR_INVALID_HANDLE
);
618 XPos
+= dc
->w
.DCOrgX
;
619 YPos
+= dc
->w
.DCOrgY
;
620 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
623 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
624 SurfaceObject
= &BitmapObject
->SurfObj
;
627 if ( dc
->w
.hPalette
!= 0 )
628 Pal
= dc
->w
.hPalette
;
629 /* FIXME: Verify if it shouldn't be PAL_BGR! */
630 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
633 // check if this DC has a DIB behind it...
634 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
636 ASSERT ( SurfaceObject
->lDelta
);
637 Result
= XLATEOBJ_iXlate(XlateObj
,
638 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
640 EngDeleteXlate(XlateObj
);
642 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
647 // if Result is still CLR_INVALID, then the "quick" method above didn't work
648 if ( bInRect
&& Result
== CLR_INVALID
)
650 // FIXME: create a 1x1 32BPP DIB, and blit to it
651 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
654 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
656 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
657 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
658 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
661 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
666 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
667 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
669 // our bitmap is no longer selected, so we can access it's stuff...
670 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
673 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
674 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
677 NtGdiDeleteObject ( hBmpTmp
);
679 NtGdiDeleteDC ( hDCTmp
);
686 /***********************************************************************
688 * Ported from WINE by sedwards 11-4-03
690 * Someone thought it would be faster to do it here and then switch back
691 * to GDI32. I dunno. Write a test and let me know.
695 SwapROP3_SrcDst(BYTE bRop3
)
697 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
700 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
701 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
702 #define DSTCOPY 0x00AA0029
703 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
707 HDC hdcDest
, INT nXDest
, INT nYDest
,
708 INT nWidth
, INT nHeight
, HDC hdcSrc
,
709 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
710 INT xMask
, INT yMask
, DWORD dwRop
)
712 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
713 HDC hDCMask
, hDC1
, hDC2
;
714 static const DWORD ROP3Table
[256] =
716 0x00000042, 0x00010289,
717 0x00020C89, 0x000300AA,
718 0x00040C88, 0x000500A9,
719 0x00060865, 0x000702C5,
720 0x00080F08, 0x00090245,
721 0x000A0329, 0x000B0B2A,
722 0x000C0324, 0x000D0B25,
723 0x000E08A5, 0x000F0001,
724 0x00100C85, 0x001100A6,
725 0x00120868, 0x001302C8,
726 0x00140869, 0x001502C9,
727 0x00165CCA, 0x00171D54,
728 0x00180D59, 0x00191CC8,
729 0x001A06C5, 0x001B0768,
730 0x001C06CA, 0x001D0766,
731 0x001E01A5, 0x001F0385,
732 0x00200F09, 0x00210248,
733 0x00220326, 0x00230B24,
734 0x00240D55, 0x00251CC5,
735 0x002606C8, 0x00271868,
736 0x00280369, 0x002916CA,
737 0x002A0CC9, 0x002B1D58,
738 0x002C0784, 0x002D060A,
739 0x002E064A, 0x002F0E2A,
740 0x0030032A, 0x00310B28,
741 0x00320688, 0x00330008,
742 0x003406C4, 0x00351864,
743 0x003601A8, 0x00370388,
744 0x0038078A, 0x00390604,
745 0x003A0644, 0x003B0E24,
746 0x003C004A, 0x003D18A4,
747 0x003E1B24, 0x003F00EA,
748 0x00400F0A, 0x00410249,
749 0x00420D5D, 0x00431CC4,
750 0x00440328, 0x00450B29,
751 0x004606C6, 0x0047076A,
752 0x00480368, 0x004916C5,
753 0x004A0789, 0x004B0605,
754 0x004C0CC8, 0x004D1954,
755 0x004E0645, 0x004F0E25,
756 0x00500325, 0x00510B26,
757 0x005206C9, 0x00530764,
758 0x005408A9, 0x00550009,
759 0x005601A9, 0x00570389,
760 0x00580785, 0x00590609,
761 0x005A0049, 0x005B18A9,
762 0x005C0649, 0x005D0E29,
763 0x005E1B29, 0x005F00E9,
764 0x00600365, 0x006116C6,
765 0x00620786, 0x00630608,
766 0x00640788, 0x00650606,
767 0x00660046, 0x006718A8,
768 0x006858A6, 0x00690145,
769 0x006A01E9, 0x006B178A,
770 0x006C01E8, 0x006D1785,
771 0x006E1E28, 0x006F0C65,
772 0x00700CC5, 0x00711D5C,
773 0x00720648, 0x00730E28,
774 0x00740646, 0x00750E26,
775 0x00761B28, 0x007700E6,
776 0x007801E5, 0x00791786,
777 0x007A1E29, 0x007B0C68,
778 0x007C1E24, 0x007D0C69,
779 0x007E0955, 0x007F03C9,
780 0x008003E9, 0x00810975,
781 0x00820C49, 0x00831E04,
782 0x00840C48, 0x00851E05,
783 0x008617A6, 0x008701C5,
784 0x008800C6, 0x00891B08,
785 0x008A0E06, 0x008B0666,
786 0x008C0E08, 0x008D0668,
787 0x008E1D7C, 0x008F0CE5,
788 0x00900C45, 0x00911E08,
789 0x009217A9, 0x009301C4,
790 0x009417AA, 0x009501C9,
791 0x00960169, 0x0097588A,
792 0x00981888, 0x00990066,
793 0x009A0709, 0x009B07A8,
794 0x009C0704, 0x009D07A6,
795 0x009E16E6, 0x009F0345,
796 0x00A000C9, 0x00A11B05,
797 0x00A20E09, 0x00A30669,
798 0x00A41885, 0x00A50065,
799 0x00A60706, 0x00A707A5,
800 0x00A803A9, 0x00A90189,
801 0x00AA0029, 0x00AB0889,
802 0x00AC0744, 0x00AD06E9,
803 0x00AE0B06, 0x00AF0229,
804 0x00B00E05, 0x00B10665,
805 0x00B21974, 0x00B30CE8,
806 0x00B4070A, 0x00B507A9,
807 0x00B616E9, 0x00B70348,
808 0x00B8074A, 0x00B906E6,
809 0x00BA0B09, 0x00BB0226,
810 0x00BC1CE4, 0x00BD0D7D,
811 0x00BE0269, 0x00BF08C9,
812 0x00C000CA, 0x00C11B04,
813 0x00C21884, 0x00C3006A,
814 0x00C40E04, 0x00C50664,
815 0x00C60708, 0x00C707AA,
816 0x00C803A8, 0x00C90184,
817 0x00CA0749, 0x00CB06E4,
818 0x00CC0020, 0x00CD0888,
819 0x00CE0B08, 0x00CF0224,
820 0x00D00E0A, 0x00D1066A,
821 0x00D20705, 0x00D307A4,
822 0x00D41D78, 0x00D50CE9,
823 0x00D616EA, 0x00D70349,
824 0x00D80745, 0x00D906E8,
825 0x00DA1CE9, 0x00DB0D75,
826 0x00DC0B04, 0x00DD0228,
827 0x00DE0268, 0x00DF08C8,
828 0x00E003A5, 0x00E10185,
829 0x00E20746, 0x00E306EA,
830 0x00E40748, 0x00E506E5,
831 0x00E61CE8, 0x00E70D79,
832 0x00E81D74, 0x00E95CE6,
833 0x00EA02E9, 0x00EB0849,
834 0x00EC02E8, 0x00ED0848,
835 0x00EE0086, 0x00EF0A08,
836 0x00F00021, 0x00F10885,
837 0x00F20B05, 0x00F3022A,
838 0x00F40B0A, 0x00F50225,
839 0x00F60265, 0x00F708C5,
840 0x00F802E5, 0x00F90845,
841 0x00FA0089, 0x00FB0A09,
842 0x00FC008A, 0x00FD0A0A,
843 0x00FE02A9, 0x00FF0062,
847 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
849 /* 1. make mask bitmap's dc */
850 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
851 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
853 /* 2. make masked Background bitmap */
855 /* 2.1 make bitmap */
856 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
857 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
858 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
860 /* 2.2 draw dest bitmap and mask */
861 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
862 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
863 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
865 /* 3. make masked Foreground bitmap */
867 /* 3.1 make bitmap */
868 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
869 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
870 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
872 /* 3.2 draw src bitmap and mask */
873 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
874 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
875 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
877 /* 4. combine two bitmap and copy it to hdcDest */
878 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
879 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
881 /* 5. restore all object */
882 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
883 NtGdiSelectObject(hDC1
, hOldBitmap2
);
884 NtGdiSelectObject(hDC2
, hOldBitmap3
);
886 /* 6. delete all temp object */
887 NtGdiDeleteObject(hBitmap2
);
888 NtGdiDeleteObject(hBitmap3
);
892 NtGdiDeleteDC(hDCMask
);
923 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
924 if (bmp
== NULL
|| Bits
== NULL
)
931 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
935 /* Only get entire lines */
936 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
937 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
939 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
941 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
942 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
946 bmp
->SurfObj
.sizlBitmap
.cx
,
947 bmp
->SurfObj
.sizlBitmap
.cy
,
948 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
952 /* FIXME: call DDI specific function here if available */
955 DPRINT ("Calling device specific BitmapBits\n");
956 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
958 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
962 DPRINT ("BitmapBits == NULL??\n");
969 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
973 BITMAPOBJ_UnlockBitmap(hBitmap
);
979 NtGdiSetBitmapDimensionEx(
987 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
995 *Size
= bmp
->dimension
;
997 bmp
->dimension
.cx
= Width
;
998 bmp
->dimension
.cy
= Height
;
1000 BITMAPOBJ_UnlockBitmap (hBitmap
);
1012 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
1013 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1017 return ((COLORREF
) -1);
1027 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1030 if (NewBrush
== NULL
)
1032 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1033 if (OldBrush
== NULL
)
1035 NtGdiDeleteObject(NewBrush
);
1038 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1039 NtGdiSelectObject(hDC
, OldBrush
);
1040 NtGdiDeleteObject(NewBrush
);
1060 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1064 XLATEOBJ
*XlateObj
= NULL
;
1065 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1066 PGDIBRUSHOBJ BrushObj
;
1067 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1068 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1070 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1072 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1075 DCDest
= DC_LockDc(hDCDest
);
1078 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1079 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1084 DC_UnlockDc(hDCDest
);
1085 /* Yes, Windows really returns TRUE in this case */
1091 if (hDCSrc
!= hDCDest
)
1093 DCSrc
= DC_LockDc(hDCSrc
);
1096 DC_UnlockDc(hDCDest
);
1097 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1098 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1103 DC_UnlockDc(hDCSrc
);
1104 DC_UnlockDc(hDCDest
);
1105 /* Yes, Windows really returns TRUE in this case */
1119 /* Offset the destination and source by the origin of their DCs. */
1120 XOriginDest
+= DCDest
->w
.DCOrgX
;
1121 YOriginDest
+= DCDest
->w
.DCOrgY
;
1124 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1125 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1128 DestRect
.left
= XOriginDest
;
1129 DestRect
.top
= YOriginDest
;
1130 DestRect
.right
= XOriginDest
+WidthDest
;
1131 DestRect
.bottom
= YOriginDest
+HeightDest
;
1133 SourceRect
.left
= XOriginSrc
;
1134 SourceRect
.top
= YOriginSrc
;
1135 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1136 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1138 /* Determine surfaces to be used in the bitblt */
1139 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1142 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1143 BitmapSrc
= BitmapDest
;
1145 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1154 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1155 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1156 if ( SourceRect
.left
< 0 )
1158 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1159 SourceRect
.left
= 0;
1161 if ( SourceRect
.top
< 0 )
1163 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1166 if ( SourceRect
.right
< -1 )
1168 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1169 SourceRect
.right
= -1;
1171 if ( SourceRect
.bottom
< -1 )
1173 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1174 SourceRect
.bottom
= -1;
1176 if ( SourceRect
.right
> sw
)
1178 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1179 SourceRect
.right
= sw
;
1181 if ( SourceRect
.bottom
> sh
)
1183 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1184 SourceRect
.bottom
= sh
;
1188 if ( SourceRect
.left
> sw
)
1190 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1191 SourceRect
.left
= 0;
1193 if ( SourceRect
.top
> sh
)
1195 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1198 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1200 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1208 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1209 if (NULL
== BrushObj
)
1211 if (UsesSource
&& hDCSrc
!= hDCDest
)
1213 DC_UnlockDc(hDCSrc
);
1215 DC_UnlockDc(hDCDest
);
1216 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1225 /* Create the XLATEOBJ. */
1228 if (DCDest
->w
.hPalette
!= 0)
1229 DestPalette
= DCDest
->w
.hPalette
;
1231 if (DCSrc
->w
.hPalette
!= 0)
1232 SourcePalette
= DCSrc
->w
.hPalette
;
1234 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1235 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1236 if (NULL
== XlateObj
)
1238 if (UsesSource
&& hDCSrc
!= hDCDest
)
1240 DC_UnlockDc(hDCSrc
);
1242 DC_UnlockDc(hDCDest
);
1243 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1248 /* Perform the bitblt operation */
1249 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1250 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1253 EngDeleteXlate(XlateObj
);
1256 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1259 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1261 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1263 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1264 if (UsesSource
&& hDCSrc
!= hDCDest
)
1266 DC_UnlockDc(hDCSrc
);
1268 DC_UnlockDc(hDCDest
);
1273 /* Internal Functions */
1276 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1282 return 2 * ((bmWidth
+15) >> 4);
1285 bmWidth
*= 3; /* fall through */
1287 return bmWidth
+ (bmWidth
& 1);
1297 return 2 * ((bmWidth
+3) >> 2);
1306 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1310 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1316 if (hBitmap
== NULL
)
1319 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1323 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1325 if (Bitmap
->SurfObj
.lDelta
>= 0)
1326 bm
.bmHeight
= -bm
.bmHeight
;
1328 res
= NtGdiCreateBitmapIndirect(&bm
);
1333 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1334 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1335 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1339 GDIOBJ_UnlockObj(hBitmap
);
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
);
1363 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1365 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1366 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1367 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1368 Bitmap
.bmPlanes
= 1;
1369 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1370 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1371 memcpy(buffer
, &Bitmap
, count
);