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.
26 #define IN_RECT(r,x,y) \
48 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
50 POINTL SourcePoint
, BrushOrigin
;
52 XLATEOBJ
*XlateObj
= NULL
;
53 HPALETTE SourcePalette
= 0, DestPalette
= 0;
54 PGDIBRUSHOBJ BrushObj
;
55 GDIBRUSHINST BrushInst
;
56 BOOL UsesSource
= ROP3_USES_SOURCE(ROP
);
57 BOOL UsesPattern
= ROP3_USES_PATTERN(ROP
);
59 DCDest
= DC_LockDc(hDCDest
);
62 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
63 SetLastWin32Error(ERROR_INVALID_HANDLE
);
69 /* Yes, Windows really returns TRUE in this case */
75 if (hDCSrc
!= hDCDest
)
77 DCSrc
= DC_LockDc(hDCSrc
);
81 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
82 SetLastWin32Error(ERROR_INVALID_HANDLE
);
89 /* Yes, Windows really returns TRUE in this case */
103 /* Offset the destination and source by the origin of their DCs. */
104 XDest
+= DCDest
->w
.DCOrgX
;
105 YDest
+= DCDest
->w
.DCOrgY
;
108 XSrc
+= DCSrc
->w
.DCOrgX
;
109 YSrc
+= DCSrc
->w
.DCOrgY
;
112 DestRect
.left
= XDest
;
113 DestRect
.top
= YDest
;
114 DestRect
.right
= XDest
+Width
;
115 DestRect
.bottom
= YDest
+Height
;
117 SourcePoint
.x
= XSrc
;
118 SourcePoint
.y
= YSrc
;
123 /* Determine surfaces to be used in the bitblt */
124 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
127 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
128 BitmapSrc
= BitmapDest
;
130 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
139 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
140 if (NULL
== BrushObj
)
142 if (UsesSource
&& hDCSrc
!= hDCDest
)
146 if(BitmapDest
!= NULL
)
148 BITMAPOBJ_UnlockBitmap(BitmapDest
);
150 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
152 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
155 SetLastWin32Error(ERROR_INVALID_HANDLE
);
158 BrushOrigin
= BrushObj
->ptOrigin
;
159 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
166 /* Create the XLATEOBJ. */
169 if (DCDest
->w
.hPalette
!= 0)
170 DestPalette
= DCDest
->w
.hPalette
;
172 if (DCSrc
->w
.hPalette
!= 0)
173 SourcePalette
= DCSrc
->w
.hPalette
;
175 /* KB41464 details how to convert between mono and color */
176 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
182 if (DCDest
->w
.bitsPerPixel
== 1)
184 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
186 else if (DCSrc
->w
.bitsPerPixel
== 1)
188 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
192 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
194 if (NULL
== XlateObj
)
196 if (UsesSource
&& hDCSrc
!= hDCDest
)
201 if(BitmapDest
!= NULL
)
203 BITMAPOBJ_UnlockBitmap(BitmapDest
);
205 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
207 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
211 BRUSHOBJ_UnlockBrush(BrushObj
);
213 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
219 /* Perform the bitblt operation */
220 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
, NULL
,
221 DCDest
->CombinedClip
, XlateObj
, &DestRect
,
223 BrushObj
? &BrushInst
.BrushObject
: NULL
,
224 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
226 if (UsesSource
&& XlateObj
!= NULL
)
227 EngDeleteXlate(XlateObj
);
229 if(BitmapDest
!= NULL
)
231 BITMAPOBJ_UnlockBitmap(BitmapDest
);
233 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
235 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
237 if (BrushObj
!= NULL
)
239 BRUSHOBJ_UnlockBrush(BrushObj
);
241 if (UsesSource
&& hDCSrc
!= hDCDest
)
266 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
268 HPALETTE SourcePalette
= 0, DestPalette
= 0;
269 PPALGDI PalDestGDI
, PalSourceGDI
;
270 USHORT PalDestMode
, PalSrcMode
;
271 ULONG TransparentColor
= 0;
274 if(!(DCDest
= DC_LockDc(hdcDst
)))
276 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
277 SetLastWin32Error(ERROR_INVALID_HANDLE
);
283 /* Yes, Windows really returns TRUE in this case */
287 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
290 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
291 SetLastWin32Error(ERROR_INVALID_HANDLE
);
305 /* Yes, Windows really returns TRUE in this case */
309 /* Offset positions */
310 xDst
+= DCDest
->w
.DCOrgX
;
311 yDst
+= DCDest
->w
.DCOrgY
;
312 xSrc
+= DCSrc
->w
.DCOrgX
;
313 ySrc
+= DCSrc
->w
.DCOrgY
;
315 if(DCDest
->w
.hPalette
)
316 DestPalette
= DCDest
->w
.hPalette
;
318 if(DCSrc
->w
.hPalette
)
319 SourcePalette
= DCSrc
->w
.hPalette
;
321 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
325 SetLastWin32Error(ERROR_INVALID_HANDLE
);
328 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
330 PALETTE_UnlockPalette(PalSourceGDI
);
333 SetLastWin32Error(ERROR_INVALID_HANDLE
);
336 if(DestPalette
!= SourcePalette
)
338 PalDestMode
= PalDestGDI
->Mode
;
339 PalSrcMode
= PalSourceGDI
->Mode
;
340 PALETTE_UnlockPalette(PalDestGDI
);
344 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
346 PALETTE_UnlockPalette(PalSourceGDI
);
348 /* Translate Transparent (RGB) Color to the source palette */
349 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
351 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
352 EngDeleteXlate(XlateObj
);
355 /* Create the XLATE object to convert colors between source and destination */
356 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
358 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
359 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
361 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
362 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
367 rcDest
.right
= rcDest
.left
+ cxDst
;
368 rcDest
.bottom
= rcDest
.top
+ cyDst
;
371 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
372 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
374 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
376 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
380 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
381 DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
382 TransparentColor
, 0);
385 BITMAPOBJ_UnlockBitmap(BitmapDest
);
386 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
394 EngDeleteXlate(XlateObj
);
411 /* NOTE: Windows also doesn't store nr. of planes separately! */
412 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
414 /* Check parameters */
415 if (!Height
|| !Width
)
417 Size
.cx
= Size
.cy
= 1;
421 Size
.cx
= abs(Width
);
422 Size
.cy
= abs(Height
);
425 /* Create the bitmap object. */
426 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
427 BitmapFormat(BitsPerPel
, BI_RGB
),
428 (Height
< 0 ? BMF_TOPDOWN
: 0) |
429 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
432 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
436 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
437 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
439 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
440 /* FIXME - bmp can be NULL!!!!!! */
441 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
442 BITMAPOBJ_UnlockBitmap( bmp
);
445 * NOTE: It's ugly practice, but we are using the object even
446 * after unlocking. Since the handle is currently known only
447 * to us it should be safe.
452 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
459 BITMAP_Cleanup(PVOID ObjectBody
)
461 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
462 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
463 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
465 if (pBmp
->dib
== NULL
)
467 ExFreePool(pBmp
->SurfObj
.pvBits
);
471 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
473 if (pBmp
->hDIBPalette
)
475 NtGdiDeleteObject(pBmp
->hDIBPalette
);
479 if (NULL
!= pBmp
->BitsLock
)
481 ExFreePoolWithTag(pBmp
->BitsLock
, TAG_BITMAPOBJ
);
482 pBmp
->BitsLock
= NULL
;
490 IntCreateCompatibleBitmap(
499 if ((Width
>= 0x10000) || (Height
>= 0x10000))
501 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
505 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
506 if (0 == Width
|| 0 == Height
)
508 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
512 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
519 NtGdiCreateCompatibleBitmap(
529 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
533 SetLastWin32Error(ERROR_INVALID_HANDLE
);
537 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
539 DPRINT ("\t\t%04x\n", Bmp
);
545 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
547 return NtGdiCreateBitmap (BM
->bmWidth
,
555 NtGdiCreateDiscardableBitmap(
560 /* FIXME: this probably should do something else */
561 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
572 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
574 /* lie and say we succeded */
585 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
589 NtGdiGetBitmapDimensionEx(
595 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
601 *Dimension
= bmp
->dimension
;
603 BITMAPOBJ_UnlockBitmap(bmp
);
609 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
612 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
613 BOOL bInRect
= FALSE
;
614 BITMAPOBJ
*BitmapObject
;
615 SURFOBJ
*SurfaceObject
;
619 dc
= DC_LockDc (hDC
);
623 SetLastWin32Error(ERROR_INVALID_HANDLE
);
631 XPos
+= dc
->w
.DCOrgX
;
632 YPos
+= dc
->w
.DCOrgY
;
633 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
636 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
637 SurfaceObject
= &BitmapObject
->SurfObj
;
640 if ( dc
->w
.hPalette
!= 0 )
641 Pal
= dc
->w
.hPalette
;
642 /* FIXME: Verify if it shouldn't be PAL_BGR! */
643 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
646 // check if this DC has a DIB behind it...
647 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
649 ASSERT ( SurfaceObject
->lDelta
);
650 Result
= XLATEOBJ_iXlate(XlateObj
,
651 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
653 EngDeleteXlate(XlateObj
);
655 BITMAPOBJ_UnlockBitmap(BitmapObject
);
660 // if Result is still CLR_INVALID, then the "quick" method above didn't work
661 if ( bInRect
&& Result
== CLR_INVALID
)
663 // FIXME: create a 1x1 32BPP DIB, and blit to it
664 HDC hDCTmp
= NtGdiCreateCompatibleDC(hDC
);
667 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
669 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
670 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
671 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
674 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
679 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
680 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
682 // our bitmap is no longer selected, so we can access it's stuff...
683 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
686 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
687 BITMAPOBJ_UnlockBitmap ( bmpobj
);
690 NtGdiDeleteObject ( hBmpTmp
);
692 NtGdiDeleteDC ( hDCTmp
);
699 /***********************************************************************
701 * Ported from WINE by sedwards 11-4-03
703 * Someone thought it would be faster to do it here and then switch back
704 * to GDI32. I dunno. Write a test and let me know.
708 SwapROP3_SrcDst(BYTE bRop3
)
710 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
713 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
714 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
715 #define DSTCOPY 0x00AA0029
716 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
720 HDC hdcDest
, INT nXDest
, INT nYDest
,
721 INT nWidth
, INT nHeight
, HDC hdcSrc
,
722 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
723 INT xMask
, INT yMask
, DWORD dwRop
)
725 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
726 HDC hDCMask
, hDC1
, hDC2
;
727 static const DWORD ROP3Table
[256] =
729 0x00000042, 0x00010289,
730 0x00020C89, 0x000300AA,
731 0x00040C88, 0x000500A9,
732 0x00060865, 0x000702C5,
733 0x00080F08, 0x00090245,
734 0x000A0329, 0x000B0B2A,
735 0x000C0324, 0x000D0B25,
736 0x000E08A5, 0x000F0001,
737 0x00100C85, 0x001100A6,
738 0x00120868, 0x001302C8,
739 0x00140869, 0x001502C9,
740 0x00165CCA, 0x00171D54,
741 0x00180D59, 0x00191CC8,
742 0x001A06C5, 0x001B0768,
743 0x001C06CA, 0x001D0766,
744 0x001E01A5, 0x001F0385,
745 0x00200F09, 0x00210248,
746 0x00220326, 0x00230B24,
747 0x00240D55, 0x00251CC5,
748 0x002606C8, 0x00271868,
749 0x00280369, 0x002916CA,
750 0x002A0CC9, 0x002B1D58,
751 0x002C0784, 0x002D060A,
752 0x002E064A, 0x002F0E2A,
753 0x0030032A, 0x00310B28,
754 0x00320688, 0x00330008,
755 0x003406C4, 0x00351864,
756 0x003601A8, 0x00370388,
757 0x0038078A, 0x00390604,
758 0x003A0644, 0x003B0E24,
759 0x003C004A, 0x003D18A4,
760 0x003E1B24, 0x003F00EA,
761 0x00400F0A, 0x00410249,
762 0x00420D5D, 0x00431CC4,
763 0x00440328, 0x00450B29,
764 0x004606C6, 0x0047076A,
765 0x00480368, 0x004916C5,
766 0x004A0789, 0x004B0605,
767 0x004C0CC8, 0x004D1954,
768 0x004E0645, 0x004F0E25,
769 0x00500325, 0x00510B26,
770 0x005206C9, 0x00530764,
771 0x005408A9, 0x00550009,
772 0x005601A9, 0x00570389,
773 0x00580785, 0x00590609,
774 0x005A0049, 0x005B18A9,
775 0x005C0649, 0x005D0E29,
776 0x005E1B29, 0x005F00E9,
777 0x00600365, 0x006116C6,
778 0x00620786, 0x00630608,
779 0x00640788, 0x00650606,
780 0x00660046, 0x006718A8,
781 0x006858A6, 0x00690145,
782 0x006A01E9, 0x006B178A,
783 0x006C01E8, 0x006D1785,
784 0x006E1E28, 0x006F0C65,
785 0x00700CC5, 0x00711D5C,
786 0x00720648, 0x00730E28,
787 0x00740646, 0x00750E26,
788 0x00761B28, 0x007700E6,
789 0x007801E5, 0x00791786,
790 0x007A1E29, 0x007B0C68,
791 0x007C1E24, 0x007D0C69,
792 0x007E0955, 0x007F03C9,
793 0x008003E9, 0x00810975,
794 0x00820C49, 0x00831E04,
795 0x00840C48, 0x00851E05,
796 0x008617A6, 0x008701C5,
797 0x008800C6, 0x00891B08,
798 0x008A0E06, 0x008B0666,
799 0x008C0E08, 0x008D0668,
800 0x008E1D7C, 0x008F0CE5,
801 0x00900C45, 0x00911E08,
802 0x009217A9, 0x009301C4,
803 0x009417AA, 0x009501C9,
804 0x00960169, 0x0097588A,
805 0x00981888, 0x00990066,
806 0x009A0709, 0x009B07A8,
807 0x009C0704, 0x009D07A6,
808 0x009E16E6, 0x009F0345,
809 0x00A000C9, 0x00A11B05,
810 0x00A20E09, 0x00A30669,
811 0x00A41885, 0x00A50065,
812 0x00A60706, 0x00A707A5,
813 0x00A803A9, 0x00A90189,
814 0x00AA0029, 0x00AB0889,
815 0x00AC0744, 0x00AD06E9,
816 0x00AE0B06, 0x00AF0229,
817 0x00B00E05, 0x00B10665,
818 0x00B21974, 0x00B30CE8,
819 0x00B4070A, 0x00B507A9,
820 0x00B616E9, 0x00B70348,
821 0x00B8074A, 0x00B906E6,
822 0x00BA0B09, 0x00BB0226,
823 0x00BC1CE4, 0x00BD0D7D,
824 0x00BE0269, 0x00BF08C9,
825 0x00C000CA, 0x00C11B04,
826 0x00C21884, 0x00C3006A,
827 0x00C40E04, 0x00C50664,
828 0x00C60708, 0x00C707AA,
829 0x00C803A8, 0x00C90184,
830 0x00CA0749, 0x00CB06E4,
831 0x00CC0020, 0x00CD0888,
832 0x00CE0B08, 0x00CF0224,
833 0x00D00E0A, 0x00D1066A,
834 0x00D20705, 0x00D307A4,
835 0x00D41D78, 0x00D50CE9,
836 0x00D616EA, 0x00D70349,
837 0x00D80745, 0x00D906E8,
838 0x00DA1CE9, 0x00DB0D75,
839 0x00DC0B04, 0x00DD0228,
840 0x00DE0268, 0x00DF08C8,
841 0x00E003A5, 0x00E10185,
842 0x00E20746, 0x00E306EA,
843 0x00E40748, 0x00E506E5,
844 0x00E61CE8, 0x00E70D79,
845 0x00E81D74, 0x00E95CE6,
846 0x00EA02E9, 0x00EB0849,
847 0x00EC02E8, 0x00ED0848,
848 0x00EE0086, 0x00EF0A08,
849 0x00F00021, 0x00F10885,
850 0x00F20B05, 0x00F3022A,
851 0x00F40B0A, 0x00F50225,
852 0x00F60265, 0x00F708C5,
853 0x00F802E5, 0x00F90845,
854 0x00FA0089, 0x00FB0A09,
855 0x00FC008A, 0x00FD0A0A,
856 0x00FE02A9, 0x00FF0062,
860 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
862 /* 1. make mask bitmap's dc */
863 hDCMask
= NtGdiCreateCompatibleDC(hdcDest
);
864 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
866 /* 2. make masked Background bitmap */
868 /* 2.1 make bitmap */
869 hDC1
= NtGdiCreateCompatibleDC(hdcDest
);
870 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
871 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
873 /* 2.2 draw dest bitmap and mask */
874 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
875 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
876 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
878 /* 3. make masked Foreground bitmap */
880 /* 3.1 make bitmap */
881 hDC2
= NtGdiCreateCompatibleDC(hdcDest
);
882 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
883 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
885 /* 3.2 draw src bitmap and mask */
886 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
887 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
888 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
890 /* 4. combine two bitmap and copy it to hdcDest */
891 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
892 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
894 /* 5. restore all object */
895 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
896 NtGdiSelectObject(hDC1
, hOldBitmap2
);
897 NtGdiSelectObject(hDC2
, hOldBitmap3
);
899 /* 6. delete all temp object */
900 NtGdiDeleteObject(hBitmap2
);
901 NtGdiDeleteObject(hBitmap3
);
905 NtGdiDeleteDC(hDCMask
);
936 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
937 if (bmp
== NULL
|| Bits
== NULL
)
944 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
948 /* Only get entire lines */
949 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
950 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
952 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
954 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
955 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
959 bmp
->SurfObj
.sizlBitmap
.cx
,
960 bmp
->SurfObj
.sizlBitmap
.cy
,
961 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
965 /* FIXME: call DDI specific function here if available */
968 DPRINT ("Calling device specific BitmapBits\n");
969 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
971 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
975 DPRINT ("BitmapBits == NULL??\n");
982 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
986 BITMAPOBJ_UnlockBitmap(bmp
);
992 NtGdiSetBitmapDimensionEx(
1000 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
1008 *Size
= bmp
->dimension
;
1010 bmp
->dimension
.cx
= Width
;
1011 bmp
->dimension
.cy
= Height
;
1013 BITMAPOBJ_UnlockBitmap (bmp
);
1025 if (NtGdiSetPixelV(hDC
,X
,Y
,Color
))
1027 return NtGdiGetPixel(hDC
,X
,Y
);
1029 return ((COLORREF
) -1);
1039 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
1042 if (NewBrush
== NULL
)
1044 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
1045 if (OldBrush
== NULL
)
1047 NtGdiDeleteObject(NewBrush
);
1050 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
1051 NtGdiSelectObject(hDC
, OldBrush
);
1052 NtGdiDeleteObject(NewBrush
);
1072 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1076 XLATEOBJ
*XlateObj
= NULL
;
1077 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1078 PGDIBRUSHOBJ BrushObj
;
1079 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1080 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1082 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1084 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1087 DCDest
= DC_LockDc(hDCDest
);
1090 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1091 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1096 DC_UnlockDc(DCDest
);
1097 /* Yes, Windows really returns TRUE in this case */
1103 if (hDCSrc
!= hDCDest
)
1105 DCSrc
= DC_LockDc(hDCSrc
);
1108 DC_UnlockDc(DCDest
);
1109 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1110 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1116 DC_UnlockDc(DCDest
);
1117 /* Yes, Windows really returns TRUE in this case */
1131 /* Offset the destination and source by the origin of their DCs. */
1132 XOriginDest
+= DCDest
->w
.DCOrgX
;
1133 YOriginDest
+= DCDest
->w
.DCOrgY
;
1136 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1137 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1140 DestRect
.left
= XOriginDest
;
1141 DestRect
.top
= YOriginDest
;
1142 DestRect
.right
= XOriginDest
+WidthDest
;
1143 DestRect
.bottom
= YOriginDest
+HeightDest
;
1145 SourceRect
.left
= XOriginSrc
;
1146 SourceRect
.top
= YOriginSrc
;
1147 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1148 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1150 /* Determine surfaces to be used in the bitblt */
1151 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1154 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1155 BitmapSrc
= BitmapDest
;
1157 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1166 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1167 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1168 if ( SourceRect
.left
< 0 )
1170 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1171 SourceRect
.left
= 0;
1173 if ( SourceRect
.top
< 0 )
1175 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1178 if ( SourceRect
.right
< -1 )
1180 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1181 SourceRect
.right
= -1;
1183 if ( SourceRect
.bottom
< -1 )
1185 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1186 SourceRect
.bottom
= -1;
1188 if ( SourceRect
.right
> sw
)
1190 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1191 SourceRect
.right
= sw
;
1193 if ( SourceRect
.bottom
> sh
)
1195 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1196 SourceRect
.bottom
= sh
;
1200 if ( SourceRect
.left
> sw
)
1202 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1203 SourceRect
.left
= 0;
1205 if ( SourceRect
.top
> sh
)
1207 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1210 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1212 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1220 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1221 if (NULL
== BrushObj
)
1223 if (UsesSource
&& hDCSrc
!= hDCDest
)
1227 DC_UnlockDc(DCDest
);
1228 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1237 /* Create the XLATEOBJ. */
1240 if (DCDest
->w
.hPalette
!= 0)
1241 DestPalette
= DCDest
->w
.hPalette
;
1243 if (DCSrc
->w
.hPalette
!= 0)
1244 SourcePalette
= DCSrc
->w
.hPalette
;
1246 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1247 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1248 if (NULL
== XlateObj
)
1250 if (UsesSource
&& hDCSrc
!= hDCDest
)
1254 DC_UnlockDc(DCDest
);
1255 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1260 /* Perform the bitblt operation */
1261 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1262 NULL
, DCDest
->CombinedClip
, XlateObj
,
1263 &DestRect
, &SourceRect
, NULL
, NULL
, NULL
,
1267 EngDeleteXlate(XlateObj
);
1270 BRUSHOBJ_UnlockBrush(BrushObj
);
1273 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1275 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1277 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1278 if (UsesSource
&& hDCSrc
!= hDCDest
)
1282 DC_UnlockDc(DCDest
);
1299 BLENDFUNCTION BlendFunc
)
1303 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1304 RECTL DestRect
, SourceRect
;
1307 BLENDOBJ BlendObj
= {BlendFunc
};
1308 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1310 DCDest
= DC_LockDc(hDCDest
);
1313 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest
);
1314 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1319 DC_UnlockDc(DCDest
);
1320 /* Yes, Windows really returns TRUE in this case */
1324 if (hDCSrc
!= hDCDest
)
1326 DCSrc
= DC_LockDc(hDCSrc
);
1329 DC_UnlockDc(DCDest
);
1330 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc
);
1331 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1337 DC_UnlockDc(DCDest
);
1338 /* Yes, Windows really returns TRUE in this case */
1347 /* Offset the destination and source by the origin of their DCs. */
1348 XOriginDest
+= DCDest
->w
.DCOrgX
;
1349 YOriginDest
+= DCDest
->w
.DCOrgY
;
1350 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1351 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1353 DestRect
.left
= XOriginDest
;
1354 DestRect
.top
= YOriginDest
;
1355 DestRect
.right
= XOriginDest
+ WidthDest
;
1356 DestRect
.bottom
= YOriginDest
+ HeightDest
;
1358 SourceRect
.left
= XOriginSrc
;
1359 SourceRect
.top
= YOriginSrc
;
1360 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
1361 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
1363 /* Determine surfaces to be used in the bitblt */
1364 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1365 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1366 BitmapSrc
= BitmapDest
;
1368 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1370 /* Create the XLATEOBJ. */
1371 if (DCDest
->w
.hPalette
!= 0)
1372 DestPalette
= DCDest
->w
.hPalette
;
1373 if (DCSrc
->w
.hPalette
!= 0)
1374 SourcePalette
= DCSrc
->w
.hPalette
;
1376 /* KB41464 details how to convert between mono and color */
1377 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
1383 if (DCDest
->w
.bitsPerPixel
== 1)
1385 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
1387 else if (DCSrc
->w
.bitsPerPixel
== 1)
1389 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
1393 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1395 if (NULL
== XlateObj
)
1397 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1398 if (BitmapSrc
!= BitmapDest
)
1399 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1400 DC_UnlockDc(DCDest
);
1401 if (hDCSrc
!= hDCDest
)
1403 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1408 /* Perform the alpha blend operation */
1409 Status
= IntEngAlphaBlend(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
1410 DCDest
->CombinedClip
, XlateObj
,
1411 &DestRect
, &SourceRect
, &BlendObj
);
1413 if (XlateObj
!= NULL
)
1414 EngDeleteXlate(XlateObj
);
1416 BITMAPOBJ_UnlockBitmap(BitmapDest
);
1417 if (BitmapSrc
!= BitmapDest
)
1418 BITMAPOBJ_UnlockBitmap(BitmapSrc
);
1419 DC_UnlockDc(DCDest
);
1420 if (hDCSrc
!= hDCDest
)
1426 /* Internal Functions */
1429 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1435 return 2 * ((bmWidth
+15) >> 4);
1438 bmWidth
*= 3; /* fall through */
1440 return bmWidth
+ (bmWidth
& 1);
1450 return 2 * ((bmWidth
+3) >> 2);
1459 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1463 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1469 if (hBitmap
== NULL
)
1472 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1476 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1478 if (Bitmap
->SurfObj
.lDelta
>= 0)
1479 bm
.bmHeight
= -bm
.bmHeight
;
1481 res
= NtGdiCreateBitmapIndirect(&bm
);
1486 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1487 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1488 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1492 GDIOBJ_UnlockObjByPtr(Bitmap
);
1498 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1502 if(count
< (INT
) sizeof(DIBSECTION
))
1504 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1508 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1510 memcpy(buffer
, bmp
->dib
, count
);
1516 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1518 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1519 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1520 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1521 Bitmap
.bmPlanes
= 1;
1522 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1523 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1524 memcpy(buffer
, &Bitmap
, count
);